Skip to content

Commit

Permalink
Implement readv, writev, and getpid
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcusGrass committed May 10, 2024
1 parent 7aab6f1 commit 99fac85
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 9 deletions.
12 changes: 11 additions & 1 deletion rusl/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [TBD] - RELEASE DATE
### Fixed

### Added

### Changed

## [0.3.1] - RELEASE DATE
### Fixed

### Added
- Implement GETPID syscall
- Implement READV syscall
- implement WRITEV syscall

### Changed

## [0.3.0] - 2024-05-05

### Fixed
Expand Down
6 changes: 6 additions & 0 deletions rusl/src/platform/compat/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ transparent_bitflags! {
}
}

impl Mode {
pub const MODE_755: Mode = Mode(
Mode::S_IRWXU.0 | Mode::S_IRGRP.0 | Mode::S_IXGRP.0 | Mode::S_IXOTH.0 | Mode::S_IROTH.0,
);
}

impl From<u32> for Mode {
#[inline]
fn from(value: u32) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion rusl/src/platform/compat/uio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct IoSlice<'a> {

impl<'a> IoSlice<'a> {
#[must_use]
pub fn new(buf: &[u8]) -> Self {
pub const fn new(buf: &[u8]) -> Self {
Self {
vec: iovec {
iov_base: buf.as_ptr().cast_mut().cast(),
Expand Down
2 changes: 2 additions & 0 deletions rusl/src/process.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
pub use clone::{clone, clone3, fork};
pub use execve::execve;
pub use exit::exit;
pub use get_pid::get_pid;
pub use signal::{add_signal_action, CatchSignal, SaSignalaction, SigInfo};
pub use wait::wait_pid;

mod execve;
mod exit;

mod clone;
mod get_pid;
mod signal;
#[cfg(test)]
mod test;
Expand Down
13 changes: 13 additions & 0 deletions rusl/src/process/get_pid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::platform::PidT;
use sc::syscall;

/// Get the pid of the calling process
/// See [Linux docs for details](https://man7.org/linux/man-pages/man2/getpid.2.html)
/// Always successful
#[inline]
#[must_use]
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
pub fn get_pid() -> PidT {
let res = unsafe { syscall!(GETPID) };
res as PidT
}
4 changes: 2 additions & 2 deletions rusl/src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use mmap::{mmap, munmap};
pub use mount::{mount, unmount};
pub use open::{open, open_at, open_at_mode, open_mode, open_raw};
pub use pipe::{pipe, pipe2};
pub use read::read;
pub use read::{read, readv};
pub use rename::{rename, rename_at, rename_at2, rename_flags};
pub use seek::{lseek, Whence};
pub use setgid::setgid;
Expand All @@ -22,7 +22,7 @@ pub use swapon::swapon;
pub use uname::uname;
pub use unlink::{rmdir, unlink, unlink_at, unlink_flags, UnlinkFlags};
pub use unshare::unshare;
pub use write::write;
pub use write::{write, writev};

mod chdir;
mod close;
Expand Down
12 changes: 11 additions & 1 deletion rusl/src/unistd/read.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sc::syscall;

use crate::platform::Fd;
use crate::platform::{Fd, IoSliceMut};

/// Attempts to read bytes up to the buffer's len into the buffer from the provided `Fd`
/// See [linux docs for details](https://man7.org/linux/man-pages/man2/read.2.html)
Expand All @@ -12,3 +12,13 @@ pub fn read(fd: Fd, buf: &mut [u8]) -> crate::Result<usize> {
bail_on_below_zero!(res, "`READ` syscall failed");
Ok(res)
}

/// Attempts to read bytes into the provided [`IoSliceMut`]'s from the provided `Fd`
/// See [linux docs for details](https://man7.org/linux/man-pages/man2/read.2.html)
/// # Errors
/// See above link
pub fn readv(fd: Fd, io: &mut [IoSliceMut]) -> crate::Result<usize> {
let res = unsafe { syscall!(READV, fd.0, io.as_mut_ptr(), io.len()) };
bail_on_below_zero!(res, "`READV` syscall failed");
Ok(res)
}
60 changes: 58 additions & 2 deletions rusl/src/unistd/test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use crate::error::Errno;
use crate::platform::OpenFlags;
use crate::platform::{IoSlice, IoSliceMut, Mode, OpenFlags};
use crate::string::unix_str::UnixStr;
use crate::unistd::{close, fcntl_get_file_status, fcntl_set_file_status, open, read, write};
use crate::unistd::read::readv;
use crate::unistd::write::writev;
use crate::unistd::{
close, fcntl_get_file_status, fcntl_set_file_status, open, open_mode, read, unlink, write,
};

#[test]
fn no_write_on_read_only() {
Expand Down Expand Up @@ -56,3 +60,55 @@ fn set_file_non_blocking() {
let new_flags = fcntl_get_file_status(fd).unwrap();
assert_eq!(OpenFlags::O_NONBLOCK, new_flags & OpenFlags::O_NONBLOCK);
}

#[test]
fn can_read_write() {
const CONTENT: &[u8; 21] = b"Test write into file\n";
let path = unix_lit!("test-files/unistd/read_write.txt");
let _ = unlink(path);
let fd = open_mode(
path,
OpenFlags::O_WRONLY | OpenFlags::O_CREAT,
Mode::MODE_755,
)
.unwrap();
write(fd, CONTENT).unwrap();
close(fd).unwrap();
let fd = open(path, OpenFlags::O_RDONLY).unwrap();
let mut buf = [0u8; CONTENT.len()];
read(fd, &mut buf).unwrap();
assert_eq!(&buf, CONTENT);
}

#[test]
fn can_read_writev() {
const PART_A: &[u8] = b"First line\n";
const PART_B: &[u8] = b"Second line\nThird line\n";
const PART_C: &[u8] = b"Fourth line\n";
let iova = IoSlice::new(PART_A);
let iovb = IoSlice::new(PART_B);
let iovc = IoSlice::new(PART_C);
let path = unix_lit!("test-files/unistd/read_writev.txt");
let _ = unlink(path);
let fd = open_mode(
path,
OpenFlags::O_WRONLY | OpenFlags::O_CREAT,
Mode::MODE_755,
)
.unwrap();
writev(fd, &[iova, iovb, iovc]).unwrap();
close(fd).unwrap();
let mut recva = [0u8; PART_A.len()];
let mut recvb = [0u8; PART_B.len()];
let mut recvc = [0u8; PART_C.len()];
let iovra = IoSliceMut::new(&mut recva);
let iovrb = IoSliceMut::new(&mut recvb);
let iovrc = IoSliceMut::new(&mut recvc);

let fd = open(path, OpenFlags::O_RDONLY).unwrap();
readv(fd, &mut [iovra, iovrb, iovrc]).unwrap();

assert_eq!(recva, PART_A);
assert_eq!(recvb, PART_B);
assert_eq!(recvc, PART_C);
}
12 changes: 11 additions & 1 deletion rusl/src/unistd/write.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sc::syscall;

use crate::platform::Fd;
use crate::platform::{Fd, IoSlice};

/// Attempts to write bytes from the buffer to the corresponding fd.
/// See [linux syscall docs](https://man7.org/linux/man-pages/man2/write.2.html)
Expand All @@ -12,3 +12,13 @@ pub fn write(fd: Fd, buf: &[u8]) -> crate::Result<usize> {
bail_on_below_zero!(res, "`WRITE` syscall failed");
Ok(res)
}

/// Attempts to write bytes from the ioslice buffers corresponding fd.
/// See [linux syscall docs](https://man7.org/linux/man-pages/man2/writev.2.html)
/// # Errors
/// See above for possible errors
pub fn writev(fd: Fd, io: &[IoSlice]) -> crate::Result<usize> {
let res = unsafe { syscall!(WRITEV, fd.0, io.as_ptr(), io.len()) };
bail_on_below_zero!(res, "`WRITEV` syscall failed");
Ok(res)
}
Empty file added rusl/test-files/unistd/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions rusl/test-files/unistd/read_write.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Test write into file
4 changes: 4 additions & 0 deletions rusl/test-files/unistd/read_writev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
First line
Second line
Third line
Fourth line
10 changes: 9 additions & 1 deletion tiny-std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rusl::string::unix_str::UnixString;
use crate::error::{Error, Result};
use crate::fs::OpenOptions;
use crate::io::{Read, Write};
use crate::unix::fd::{OwnedFd, RawFd};
use crate::unix::fd::{BorrowedFd, OwnedFd, RawFd};

const DEV_NULL: &UnixStr = UnixStr::from_str_checked("/dev/null\0");

Expand Down Expand Up @@ -614,6 +614,14 @@ pub fn spawn<const N: usize, CL: PreExec>(

pub struct AnonPipe(OwnedFd);

impl AnonPipe {
#[inline]
#[must_use]
pub fn borrow_fd(&self) -> BorrowedFd {
BorrowedFd::new(self.0 .0)
}
}

impl Read for AnonPipe {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
Expand Down

0 comments on commit 99fac85

Please sign in to comment.