mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-01-31 01:21:46 -05:00
implement pread* and pwrite* syscalls
This commit is contained in:
@@ -67,10 +67,10 @@
|
||||
| 0x40 (64) | write | (unsigned int fd, const char *buf, size_t count) | __arm64_sys_write | true |
|
||||
| 0x41 (65) | readv | (unsigned long fd, const struct iovec *vec, unsigned long vlen) | __arm64_sys_readv | true |
|
||||
| 0x42 (66) | writev | (unsigned long fd, const struct iovec *vec, unsigned long vlen) | __arm64_sys_writev | true |
|
||||
| 0x43 (67) | pread64 | (unsigned int fd, char *buf, size_t count, loff_t pos) | __arm64_sys_pread64 | false |
|
||||
| 0x44 (68) | pwrite64 | (unsigned int fd, const char *buf, size_t count, loff_t pos) | __arm64_sys_pwrite64 | false |
|
||||
| 0x45 (69) | preadv | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) | __arm64_sys_preadv | false |
|
||||
| 0x46 (70) | pwritev | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) | __arm64_sys_pwritev | false |
|
||||
| 0x43 (67) | pread64 | (unsigned int fd, char *buf, size_t count, loff_t pos) | __arm64_sys_pread64 | true |
|
||||
| 0x44 (68) | pwrite64 | (unsigned int fd, const char *buf, size_t count, loff_t pos) | __arm64_sys_pwrite64 | true |
|
||||
| 0x45 (69) | preadv | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) | __arm64_sys_preadv | true |
|
||||
| 0x46 (70) | pwritev | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h) | __arm64_sys_pwritev | true |
|
||||
| 0x47 (71) | sendfile64 | (int out_fd, int in_fd, loff_t *offset, size_t count) | __arm64_sys_sendfile64 | true |
|
||||
| 0x48 (72) | pselect6 | (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct __kernel_timespec *tsp, void *sig) | __arm64_sys_pselect6 | true |
|
||||
| 0x49 (73) | ppoll | (struct pollfd *ufds, unsigned int nfds, struct __kernel_timespec *tsp, const sigset_t *sigmask, size_t sigsetsize) | __arm64_sys_ppoll | true |
|
||||
@@ -270,8 +270,8 @@
|
||||
| 0x11b (283) | membarrier | (int cmd, unsigned int flags, int cpu_id) | __arm64_sys_membarrier | false |
|
||||
| 0x11c (284) | mlock2 | (unsigned long start, size_t len, int flags) | __arm64_sys_mlock2 | false |
|
||||
| 0x11d (285) | copy_file_range | (int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) | __arm64_sys_copy_file_range | false |
|
||||
| 0x11e (286) | preadv2 | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) | __arm64_sys_preadv2 | false |
|
||||
| 0x11f (287) | pwritev2 | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) | __arm64_sys_pwritev2 | false |
|
||||
| 0x11e (286) | preadv2 | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) | __arm64_sys_preadv2 | true |
|
||||
| 0x11f (287) | pwritev2 | (unsigned long fd, const struct iovec *vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h, rwf_t flags) | __arm64_sys_pwritev2 | true |
|
||||
| 0x120 (288) | pkey_mprotect | (unsigned long start, size_t len, unsigned long prot, int pkey) | __arm64_sys_pkey_mprotect | false |
|
||||
| 0x121 (289) | pkey_alloc | (unsigned long flags, unsigned long init_val) | __arm64_sys_pkey_alloc | false |
|
||||
| 0x122 (290) | pkey_free | (int pkey) | __arm64_sys_pkey_free | false |
|
||||
|
||||
@@ -24,8 +24,8 @@ use crate::{
|
||||
chown::sys_fchown,
|
||||
close::sys_close,
|
||||
ioctl::sys_ioctl,
|
||||
iov::{sys_readv, sys_writev},
|
||||
rw::{sys_read, sys_write},
|
||||
iov::{sys_preadv, sys_preadv2, sys_pwritev, sys_pwritev2, sys_readv, sys_writev},
|
||||
rw::{sys_pread64, sys_pwrite64, sys_read, sys_write},
|
||||
seek::sys_lseek,
|
||||
splice::sys_sendfile,
|
||||
stat::sys_fstat,
|
||||
@@ -172,6 +172,42 @@ pub async fn handle_syscall() {
|
||||
0x40 => sys_write(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
|
||||
0x41 => sys_readv(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
|
||||
0x42 => sys_writev(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
|
||||
0x43 => {
|
||||
sys_pread64(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
arg4 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x44 => {
|
||||
sys_pwrite64(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
arg4 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x45 => {
|
||||
sys_preadv(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
arg4 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x46 => {
|
||||
sys_pwritev(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
arg4 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x47 => {
|
||||
sys_sendfile(
|
||||
arg1.into(),
|
||||
@@ -364,6 +400,26 @@ pub async fn handle_syscall() {
|
||||
.await
|
||||
}
|
||||
0x116 => sys_getrandom(TUA::from_value(arg1 as _), arg2 as _, arg3 as _).await,
|
||||
0x11e => {
|
||||
sys_preadv2(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
arg4 as _,
|
||||
arg5 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x11f => {
|
||||
sys_pwritev2(
|
||||
arg1.into(),
|
||||
TUA::from_value(arg2 as _),
|
||||
arg3 as _,
|
||||
arg4 as _,
|
||||
arg5 as _,
|
||||
)
|
||||
.await
|
||||
}
|
||||
0x125 => Err(KernelError::NotSupported),
|
||||
0x1b7 => {
|
||||
sys_faccessat2(
|
||||
|
||||
@@ -84,6 +84,10 @@ impl Tty {
|
||||
#[async_trait]
|
||||
impl FileOps for Tty {
|
||||
async fn read(&mut self, _ctx: &mut FileCtx, usr_buf: UA, count: usize) -> Result<usize> {
|
||||
self.readat(usr_buf, count, 0).await
|
||||
}
|
||||
|
||||
async fn readat(&mut self, usr_buf: UA, count: usize, _offset: u64) -> Result<usize> {
|
||||
let (cooked_pipe, eof_fut) = {
|
||||
let cooker = self.input_cooker.lock_save_irq();
|
||||
|
||||
@@ -129,7 +133,11 @@ impl FileOps for Tty {
|
||||
})
|
||||
}
|
||||
|
||||
async fn write(&mut self, _ctx: &mut FileCtx, mut ptr: UA, count: usize) -> Result<usize> {
|
||||
async fn write(&mut self, _ctx: &mut FileCtx, ptr: UA, count: usize) -> Result<usize> {
|
||||
self.writeat(ptr, count, 0).await
|
||||
}
|
||||
|
||||
async fn writeat(&mut self, mut ptr: UA, count: usize, _offset: u64) -> Result<usize> {
|
||||
const CHUNK_SZ: usize = 128;
|
||||
|
||||
let mut remaining = count;
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
CharDriver, DriverManager, OpenableDevice, ReservedMajors, fs::dev::devfs,
|
||||
init::PlatformBus,
|
||||
},
|
||||
fs::{fops::FileOps, open_file::FileCtx, open_file::OpenFile},
|
||||
fs::{fops::FileOps, open_file::OpenFile},
|
||||
kernel_driver,
|
||||
};
|
||||
use alloc::string::ToString;
|
||||
@@ -22,12 +22,12 @@ struct NullFileOps;
|
||||
|
||||
#[async_trait]
|
||||
impl FileOps for NullFileOps {
|
||||
async fn read(&mut self, _ctx: &mut FileCtx, _buf: UA, _count: usize) -> Result<usize> {
|
||||
async fn readat(&mut self, _buf: UA, _count: usize, _offset: u64) -> Result<usize> {
|
||||
// EOF
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
async fn write(&mut self, _ctx: &mut FileCtx, _buf: UA, count: usize) -> Result<usize> {
|
||||
async fn writeat(&mut self, _buf: UA, count: usize, _offset: u64) -> Result<usize> {
|
||||
// Pretend we wrote everything successfully.
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@ struct ZeroFileOps;
|
||||
|
||||
#[async_trait]
|
||||
impl FileOps for ZeroFileOps {
|
||||
async fn read(&mut self, _ctx: &mut FileCtx, mut buf: UA, mut count: usize) -> Result<usize> {
|
||||
async fn read(&mut self, _ctx: &mut FileCtx, buf: UA, count: usize) -> Result<usize> {
|
||||
self.readat(buf, count, 0).await
|
||||
}
|
||||
|
||||
async fn readat(&mut self, mut buf: UA, mut count: usize, _offset: u64) -> Result<usize> {
|
||||
let requested = count;
|
||||
|
||||
while count > 0 {
|
||||
@@ -39,7 +43,11 @@ impl FileOps for ZeroFileOps {
|
||||
Ok(requested)
|
||||
}
|
||||
|
||||
async fn write(&mut self, _ctx: &mut FileCtx, _buf: UA, count: usize) -> Result<usize> {
|
||||
async fn write(&mut self, _ctx: &mut FileCtx, buf: UA, count: usize) -> Result<usize> {
|
||||
self.writeat(buf, count, 0).await
|
||||
}
|
||||
|
||||
async fn writeat(&mut self, _buf: UA, count: usize, _offset: u64) -> Result<usize> {
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
|
||||
@@ -62,10 +62,18 @@ impl FileOps for DirFile {
|
||||
Err(FsError::IsADirectory.into())
|
||||
}
|
||||
|
||||
async fn readat(&mut self, _buf: UA, _count: usize, _offset: u64) -> Result<usize> {
|
||||
Err(FsError::IsADirectory.into())
|
||||
}
|
||||
|
||||
async fn write(&mut self, _ctx: &mut FileCtx, _buf: UA, _count: usize) -> Result<usize> {
|
||||
Err(FsError::IsADirectory.into())
|
||||
}
|
||||
|
||||
async fn writeat(&mut self, _buf: UA, _count: usize, _offset: u64) -> Result<usize> {
|
||||
Err(FsError::IsADirectory.into())
|
||||
}
|
||||
|
||||
async fn readdir<'a>(&'a mut self, ctx: &'a mut FileCtx) -> Result<OpenFileDirIter<'a>> {
|
||||
if self.inode.getattr().await?.file_type != FileType::Directory {
|
||||
return Err(FsError::NotADirectory.into());
|
||||
|
||||
@@ -42,16 +42,32 @@ macro_rules! process_iovec {
|
||||
pub trait FileOps: Send + Sync {
|
||||
/// Reads data from the current file position into `buf`.
|
||||
/// The file's cursor is advanced by the number of bytes read.
|
||||
async fn read(&mut self, ctx: &mut FileCtx, buf: UA, count: usize) -> Result<usize>;
|
||||
async fn read(&mut self, ctx: &mut FileCtx, buf: UA, count: usize) -> Result<usize> {
|
||||
let total_bytes_read = self.readat(buf, count, ctx.pos).await?;
|
||||
ctx.pos += total_bytes_read as u64;
|
||||
Ok(total_bytes_read)
|
||||
}
|
||||
|
||||
async fn readat(&mut self, buf: UA, count: usize, offset: u64) -> Result<usize>;
|
||||
|
||||
/// Writes data from `buf` to the current file position.
|
||||
/// The file's cursor is advanced by the number of bytes written.
|
||||
async fn write(&mut self, ctx: &mut FileCtx, buf: UA, count: usize) -> Result<usize>;
|
||||
async fn write(&mut self, ctx: &mut FileCtx, buf: UA, count: usize) -> Result<usize> {
|
||||
let total_bytes_written = self.writeat(buf, count, ctx.pos).await?;
|
||||
ctx.pos += total_bytes_written as u64;
|
||||
Ok(total_bytes_written)
|
||||
}
|
||||
|
||||
async fn writeat(&mut self, buf: UA, count: usize, offset: u64) -> Result<usize>;
|
||||
|
||||
async fn readv(&mut self, ctx: &mut FileCtx, iovecs: &[IoVec]) -> Result<usize> {
|
||||
process_iovec!(iovecs, |addr, count| self.read(ctx, addr, count)).await
|
||||
}
|
||||
|
||||
async fn readvat(&mut self, iovecs: &[IoVec], offset: u64) -> Result<usize> {
|
||||
process_iovec!(iovecs, |addr, count| self.readat(addr, count, offset)).await
|
||||
}
|
||||
|
||||
async fn readdir<'a>(&'a mut self, _ctx: &'a mut FileCtx) -> Result<OpenFileDirIter<'a>> {
|
||||
Err(FsError::NotADirectory.into())
|
||||
}
|
||||
@@ -60,6 +76,10 @@ pub trait FileOps: Send + Sync {
|
||||
process_iovec!(iovecs, |addr, count| self.write(ctx, addr, count)).await
|
||||
}
|
||||
|
||||
async fn writevat(&mut self, iovecs: &[IoVec], offset: u64) -> Result<usize> {
|
||||
process_iovec!(iovecs, |addr, count| self.writeat(addr, count, offset)).await
|
||||
}
|
||||
|
||||
/// Puts the current task to sleep until a call to `read()` would no longer
|
||||
/// block.
|
||||
fn poll_read_ready(&self) -> Pin<Box<dyn Future<Output = Result<()>> + 'static + Send>> {
|
||||
|
||||
@@ -61,6 +61,10 @@ impl PipeReader {
|
||||
#[async_trait]
|
||||
impl FileOps for PipeReader {
|
||||
async fn read(&mut self, _ctx: &mut FileCtx, u_buf: UA, count: usize) -> Result<usize> {
|
||||
self.readat(u_buf, count, 0).await
|
||||
}
|
||||
|
||||
async fn readat(&mut self, u_buf: UA, count: usize, _offset: u64) -> Result<usize> {
|
||||
if count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
@@ -73,6 +77,10 @@ impl FileOps for PipeReader {
|
||||
Err(KernelError::BadFd)
|
||||
}
|
||||
|
||||
async fn writeat(&mut self, _buf: UA, _count: usize, _offset: u64) -> Result<usize> {
|
||||
Err(KernelError::BadFd)
|
||||
}
|
||||
|
||||
async fn seek(&mut self, _ctx: &mut FileCtx, _pos: SeekFrom) -> Result<u64> {
|
||||
Err(KernelError::SeekPipe)
|
||||
}
|
||||
@@ -135,7 +143,15 @@ impl FileOps for PipeWriter {
|
||||
Err(KernelError::BadFd)
|
||||
}
|
||||
|
||||
async fn readat(&mut self, _buf: UA, _count: usize, _offset: u64) -> Result<usize> {
|
||||
Err(KernelError::BadFd)
|
||||
}
|
||||
|
||||
async fn write(&mut self, _ctx: &mut FileCtx, u_buf: UA, count: usize) -> Result<usize> {
|
||||
self.writeat(u_buf, count, 0).await
|
||||
}
|
||||
|
||||
async fn writeat(&mut self, u_buf: UA, count: usize, _offset: u64) -> Result<usize> {
|
||||
if count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
@@ -31,11 +31,11 @@ impl RegFile {
|
||||
impl FileOps for RegFile {
|
||||
/// Reads data from the current file position into `buf`. The file's cursor
|
||||
/// is advanced by the number of bytes read.
|
||||
async fn read(
|
||||
async fn readat(
|
||||
&mut self,
|
||||
ctx: &mut FileCtx,
|
||||
mut user_buf: UA,
|
||||
mut count: usize,
|
||||
mut offset: u64,
|
||||
) -> Result<usize> {
|
||||
let mut pg = ClaimedPage::alloc_zeroed()?;
|
||||
let kbuf = pg.as_slice_mut();
|
||||
@@ -45,7 +45,7 @@ impl FileOps for RegFile {
|
||||
let chunk_sz = min(PAGE_SIZE, count);
|
||||
copy_from_user_slice(user_buf, &mut kbuf[..chunk_sz]).await?;
|
||||
|
||||
let bytes_read = self.inode.read_at(ctx.pos, &mut kbuf[..chunk_sz]).await?;
|
||||
let bytes_read = self.inode.read_at(offset, &mut kbuf[..chunk_sz]).await?;
|
||||
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
@@ -53,7 +53,7 @@ impl FileOps for RegFile {
|
||||
|
||||
copy_to_user_slice(&kbuf[..bytes_read], user_buf).await?;
|
||||
|
||||
ctx.pos += bytes_read as u64;
|
||||
offset += bytes_read as u64;
|
||||
total_bytes_read += bytes_read;
|
||||
user_buf = user_buf.add_bytes(bytes_read);
|
||||
count -= bytes_read;
|
||||
@@ -64,7 +64,7 @@ impl FileOps for RegFile {
|
||||
|
||||
/// Writes data from `buf` to the current file position.
|
||||
/// The file's cursor is advanced by the number of bytes written.
|
||||
async fn write(&mut self, ctx: &mut FileCtx, mut buf: UA, mut count: usize) -> Result<usize> {
|
||||
async fn writeat(&mut self, mut buf: UA, mut count: usize, mut offset: u64) -> Result<usize> {
|
||||
let mut pg = ClaimedPage::alloc_zeroed()?;
|
||||
let kbuf = pg.as_slice_mut();
|
||||
let mut total_bytes_written = 0;
|
||||
@@ -74,7 +74,7 @@ impl FileOps for RegFile {
|
||||
|
||||
copy_from_user_slice(buf, &mut kbuf[..chunk_sz]).await?;
|
||||
|
||||
let bytes_written = self.inode.write_at(ctx.pos, &kbuf[..chunk_sz]).await?;
|
||||
let bytes_written = self.inode.write_at(offset, &kbuf[..chunk_sz]).await?;
|
||||
|
||||
// If we wrote 0 bytes, the disk might be full or the file cannot be
|
||||
// extended.
|
||||
@@ -82,7 +82,7 @@ impl FileOps for RegFile {
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.pos += bytes_written as u64;
|
||||
offset += bytes_written as u64;
|
||||
total_bytes_written += bytes_written;
|
||||
count -= bytes_written;
|
||||
buf = buf.add_bytes(bytes_written);
|
||||
|
||||
@@ -45,3 +45,51 @@ pub async fn sys_readv(fd: Fd, iov_ptr: TUA<IoVec>, no_iov: usize) -> Result<usi
|
||||
|
||||
ops.readv(state, &iovs).await
|
||||
}
|
||||
|
||||
pub async fn sys_pwritev(fd: Fd, iov_ptr: TUA<IoVec>, no_iov: usize, offset: u64) -> Result<usize> {
|
||||
sys_pwritev2(fd, iov_ptr, no_iov, offset, 0).await
|
||||
}
|
||||
|
||||
pub async fn sys_preadv(fd: Fd, iov_ptr: TUA<IoVec>, no_iov: usize, offset: u64) -> Result<usize> {
|
||||
sys_preadv2(fd, iov_ptr, no_iov, offset, 0).await
|
||||
}
|
||||
|
||||
pub async fn sys_pwritev2(
|
||||
fd: Fd,
|
||||
iov_ptr: TUA<IoVec>,
|
||||
no_iov: usize,
|
||||
offset: u64,
|
||||
_flags: u32, // TODO: implement these flags
|
||||
) -> Result<usize> {
|
||||
let file = current_task()
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
let iovs = copy_obj_array_from_user(iov_ptr, no_iov).await?;
|
||||
|
||||
let (ops, _state) = &mut *file.lock().await;
|
||||
|
||||
ops.writevat(&iovs, offset).await
|
||||
}
|
||||
|
||||
pub async fn sys_preadv2(
|
||||
fd: Fd,
|
||||
iov_ptr: TUA<IoVec>,
|
||||
no_iov: usize,
|
||||
offset: u64,
|
||||
_flags: u32,
|
||||
) -> Result<usize> {
|
||||
let file = current_task()
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
let iovs = copy_obj_array_from_user(iov_ptr, no_iov).await?;
|
||||
|
||||
let (ops, _state) = &mut *file.lock().await;
|
||||
|
||||
ops.readvat(&iovs, offset).await
|
||||
}
|
||||
|
||||
@@ -27,3 +27,27 @@ pub async fn sys_read(fd: Fd, user_buf: UA, count: usize) -> Result<usize> {
|
||||
|
||||
ops.read(ctx, user_buf, count).await
|
||||
}
|
||||
|
||||
pub async fn sys_pwrite64(fd: Fd, user_buf: UA, count: usize, offset: u64) -> Result<usize> {
|
||||
let file = current_task()
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
let (ops, _ctx) = &mut *file.lock().await;
|
||||
|
||||
ops.writeat(user_buf, count, offset).await
|
||||
}
|
||||
|
||||
pub async fn sys_pread64(fd: Fd, user_buf: UA, count: usize, offset: u64) -> Result<usize> {
|
||||
let file = current_task()
|
||||
.fd_table
|
||||
.lock_save_irq()
|
||||
.get(fd)
|
||||
.ok_or(KernelError::BadFd)?;
|
||||
|
||||
let (ops, _ctx) = &mut *file.lock().await;
|
||||
|
||||
ops.readat(user_buf, count, offset).await
|
||||
}
|
||||
|
||||
@@ -482,13 +482,17 @@ fn test_ftruncate() {
|
||||
let mut buffer = [1u8; 5];
|
||||
unsafe {
|
||||
let fd = libc::open(c_file.as_ptr(), libc::O_RDWR | libc::O_CREAT, 0o777);
|
||||
let ret = libc::write(fd, data.as_ptr() as *const libc::c_void, data.len());
|
||||
let ret = libc::pwrite64(fd, data.as_ptr() as *const libc::c_void, data.len(), 0);
|
||||
if ret < 0 || ret as usize != data.len() {
|
||||
panic!("write failed");
|
||||
}
|
||||
libc::ftruncate(fd, 5);
|
||||
libc::lseek(fd, 0, libc::SEEK_SET);
|
||||
let ret = libc::read(fd, buffer.as_mut_ptr() as *mut libc::c_void, buffer.len());
|
||||
let ret = libc::pread64(
|
||||
fd,
|
||||
buffer.as_mut_ptr() as *mut libc::c_void,
|
||||
buffer.len(),
|
||||
0,
|
||||
);
|
||||
if ret < 0 || ret as usize != 5 {
|
||||
panic!("read failed");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user