Skip to content

Commit

Permalink
Rusl readv, writev tiny-cli rework (#27)
Browse files Browse the repository at this point in the history
* Implement readv, writev, and getpid

* Update tiny-cli bool parsing

* tiny-cli Can parse positional arguments, with weird results

* Fix up lints

* Fix up versions and doc-lints
  • Loading branch information
MarcusGrass authored Aug 24, 2024
1 parent 7aab6f1 commit bd3e75a
Show file tree
Hide file tree
Showing 29 changed files with 752 additions and 186 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ for applications that can be threaded.
static relocation if `aux` feature isn't enabled, since that will result in a botched binary).
17. [ ] Path operations on &UnixStr
18. [x] Implement `from_str` on &UnixStr
19. [x] Throw a rusl::Error instead of Utf8Error on `as_str`
19. [x] Throw a rusl::Error instead of Utf8Error on `as_str`
20. [x] Cli err on two optional positional args, err on subcommand + positional combo
2 changes: 1 addition & 1 deletion rusl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rusl"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
license = "MPL-2.0"
readme = "../Readme.md"
Expand Down
13 changes: 12 additions & 1 deletion rusl/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@ 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] - 2024-08-24

### Fixed

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

### Changed

## [0.3.0] - 2024-05-05

### Fixed
Expand Down
7 changes: 6 additions & 1 deletion rusl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#![allow(unused_doc_comments)]
#![cfg_attr(not(test), no_std)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions, clippy::similar_names)]
#![allow(
clippy::module_name_repetitions,
clippy::similar_names,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap
)]
#![cfg_attr(test, allow(clippy::ignored_unit_patterns))]

#[cfg(feature = "alloc")]
Expand Down
6 changes: 1 addition & 5 deletions rusl/src/platform/compat/io_uring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,11 +714,7 @@ impl IoUringSubmissionQueueEntry {
ioprio: 0,
fd: 0,
__bindgen_anon_1: io_uring_sqe__bindgen_ty_1 {
off: if let Some(cmpl) = await_completions {
cmpl
} else {
0
},
off: await_completions.unwrap_or_default(),
},
__bindgen_anon_2: io_uring_sqe__bindgen_ty_2 {
addr: core::ptr::from_ref::<TimeSpec>(ts) as u64,
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/string/unix_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl UnixString {
for (ind, byte) in s.iter().enumerate() {
if *byte == NULL_BYTE {
return if ind == len - 1 {
unsafe { Ok(core::mem::transmute(s)) }
unsafe { Ok(core::mem::transmute::<Vec<u8>, Self>(s)) }
} else {
Err(Error::no_code("Tried to instantiate UnixStr from an invalid &str, a null byte was found but out of place"))
};
Expand All @@ -69,7 +69,7 @@ impl UnixString {
for (ind, byte) in s.iter().enumerate() {
if *byte == NULL_BYTE {
return if ind == len - 1 {
unsafe { Ok(core::mem::transmute(s.to_vec())) }
unsafe { Ok(core::mem::transmute::<Vec<u8>, Self>(s.to_vec())) }
} else {
Err(Error::no_code("Tried to instantiate UnixStr from an invalid &str, a null byte was found but out of place"))
};
Expand Down
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
2 changes: 1 addition & 1 deletion tiny-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tiny-cli"
version = "0.2.1"
version = "0.3.0"
edition = "2021"
license = "MPL-2.0"
readme = "../Readme.md"
Expand Down
12 changes: 12 additions & 0 deletions tiny-cli/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed

## [v0.3.0] - 2024-08-24

### Fixed
- Some aliases not registering properly

### Added
- Positional arguments now accepted, and the default for untagged fields

### Changed
- Bools are always optional and should never be specified as `True` or `False`
- Options must now be specified as either `long` or `short` with their alias

## [v0.2.1] - 2024-05-05
### Fixed

Expand Down
Loading

0 comments on commit bd3e75a

Please sign in to comment.