Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ members = [
"userspace/repro_fork",
"userspace/shell_pipeline",
"userspace/vibix_abi",
"userspace/vibix_libc",
"userspace/vibix_libc_defs",
]
# tests/pjdfstest is a vendored copy of saidsay-so/pjdfstest (2-clause BSD). It
# is intentionally kept outside the workspace until #581 wires it into xtask —
Expand Down
15 changes: 15 additions & 0 deletions userspace/vibix_libc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "vibix_libc"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
description = "C-ABI shim that delegates to vibix_abi syscall wrappers"

[lib]
name = "vibix_libc"
path = "src/lib.rs"
crate-type = ["rlib"]

[dependencies]
vibix_abi = { path = "../vibix_abi" }
7 changes: 7 additions & 0 deletions userspace/vibix_libc/src/errno.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! errno support -- re-exports vibix_abi's thread-local ERRNO and
//! __errno_location symbol.
//!
//! The actual `__errno_location` symbol is defined in `vibix_abi::errno`.
//! This module simply re-exports the ERRNO cell for internal use.

pub use vibix_abi::errno::ERRNO;
28 changes: 28 additions & 0 deletions userspace/vibix_libc/src/fcntl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! File control operations: open, openat.

use crate::helpers::syscall_ret;
use vibix_abi::syscall;

// Syscall numbers (Linux x86_64)
const SYS_OPEN: u64 = 2;
const SYS_OPENAT: u64 = 257;

/// Open a file by path.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string pointer.
#[no_mangle]
pub unsafe extern "C" fn open(pathname: *const u8, flags: i32, mode: u32) -> i32 {
let ret = syscall!(SYS_OPEN, pathname, flags, mode);
syscall_ret(ret) as i32
}

/// Open a file relative to a directory fd.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string pointer.
#[no_mangle]
pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const u8, flags: i32, mode: u32) -> i32 {
let ret = syscall!(SYS_OPENAT, dirfd, pathname, flags, mode);
syscall_ret(ret) as i32
}
15 changes: 15 additions & 0 deletions userspace/vibix_libc/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//! Internal helpers for converting syscall return values to C-style returns.

use vibix_abi::errno::ERRNO;

/// Convert a raw syscall return (negative = -errno) into C return convention:
/// on success returns the non-negative value; on error sets ERRNO and returns -1.
#[inline]
pub(crate) fn syscall_ret(ret: i64) -> i64 {
if ret < 0 {
ERRNO.set((-ret) as i32);
-1
} else {
ret
}
}
22 changes: 22 additions & 0 deletions userspace/vibix_libc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! `vibix_libc` -- C-ABI shim that exposes POSIX-like symbols backed by
//! vibix_abi syscall wrappers.
//!
//! Each `#[no_mangle] pub unsafe extern "C" fn` delegates to the raw syscall
//! via `vibix_abi::syscall!()`. On error, the function sets errno and returns
//! -1 (matching POSIX semantics).

#![no_std]

// The `syscall!` macro is used in submodules via `vibix_abi::syscall!`.

pub use vibix_abi::errno::ERRNO;

mod helpers;

pub mod errno;
pub mod fcntl;
pub mod stat;
pub mod unistd;

/// Re-export the defs crate types for convenience.
pub use vibix_abi;
Comment on lines +21 to +22
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix misleading documentation comment.

The comment says "Re-export the defs crate types" but the code re-exports vibix_abi, not vibix_libc_defs. Either update the comment to accurately describe what's being re-exported, or add vibix_libc_defs as a dependency and re-export it instead.

✏️ Suggested fix
-/// Re-export the defs crate types for convenience.
+/// Re-export the ABI crate for convenience.
 pub use vibix_abi;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Re-export the defs crate types for convenience.
pub use vibix_abi;
/// Re-export the ABI crate for convenience.
pub use vibix_abi;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@userspace/vibix_libc/src/lib.rs` around lines 21 - 22, The doc comment is
inaccurate — it claims to re-export "defs" crate types but the code re-exports
the vibix_abi crate; either update the comment to state that vibix_abi is being
re-exported or actually re-export vibix_libc_defs by adding it as a dependency
and changing the pub use accordingly; locate the pub use vibix_abi statement and
replace or adjust its comment or the symbol to match (use vibix_abi or pub use
vibix_libc_defs) so the comment and the exported crate name (vibix_abi /
vibix_libc_defs) are consistent.

63 changes: 63 additions & 0 deletions userspace/vibix_libc/src/stat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! File status operations: stat, fstat, lstat, chmod, chown.

use crate::helpers::syscall_ret;
use vibix_abi::syscall;

// Syscall numbers (Linux x86_64)
const SYS_STAT: u64 = 4;
const SYS_FSTAT: u64 = 5;
const SYS_LSTAT: u64 = 6;
const SYS_CHMOD: u64 = 90;
const SYS_CHOWN: u64 = 92;

/// Get file status by path.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string; `statbuf` must point
/// to a valid `struct stat`-sized buffer.
#[no_mangle]
pub unsafe extern "C" fn stat(pathname: *const u8, statbuf: *mut u8) -> i32 {
let ret = syscall!(SYS_STAT, pathname, statbuf);
syscall_ret(ret) as i32
}

/// Get file status by fd.
///
/// # Safety
/// `statbuf` must point to a valid `struct stat`-sized buffer.
#[no_mangle]
pub unsafe extern "C" fn fstat(fd: i32, statbuf: *mut u8) -> i32 {
let ret = syscall!(SYS_FSTAT, fd, statbuf);
syscall_ret(ret) as i32
}

/// Get file status of a symlink (does not follow links).
///
/// # Safety
/// `pathname` must be a valid null-terminated C string; `statbuf` must point
/// to a valid `struct stat`-sized buffer.
#[no_mangle]
pub unsafe extern "C" fn lstat(pathname: *const u8, statbuf: *mut u8) -> i32 {
let ret = syscall!(SYS_LSTAT, pathname, statbuf);
syscall_ret(ret) as i32
}

/// Change file permissions.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string.
#[no_mangle]
pub unsafe extern "C" fn chmod(pathname: *const u8, mode: u32) -> i32 {
let ret = syscall!(SYS_CHMOD, pathname, mode);
syscall_ret(ret) as i32
}

/// Change file owner and group.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string.
#[no_mangle]
pub unsafe extern "C" fn chown(pathname: *const u8, owner: u32, group: u32) -> i32 {
let ret = syscall!(SYS_CHOWN, pathname, owner, group);
syscall_ret(ret) as i32
}
142 changes: 142 additions & 0 deletions userspace/vibix_libc/src/unistd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//! Unix-style operations: read, write, close, link, unlink, symlink, readlink,
//! mkdir, rmdir, rename, getcwd, chdir.

use crate::helpers::syscall_ret;
use vibix_abi::syscall;

// Syscall numbers (Linux x86_64)
const SYS_READ: u64 = 0;
const SYS_WRITE: u64 = 1;
const SYS_CLOSE: u64 = 3;
const SYS_GETCWD: u64 = 79;
const SYS_CHDIR: u64 = 80;
const SYS_RENAME: u64 = 82;
const SYS_MKDIR: u64 = 83;
const SYS_RMDIR: u64 = 84;
const SYS_LINK: u64 = 86;
const SYS_UNLINK: u64 = 87;
const SYS_SYMLINK: u64 = 88;
const SYS_READLINK: u64 = 89;

/// Read from a file descriptor.
///
/// # Safety
/// `buf` must be a valid pointer to a buffer of at least `count` bytes.
#[no_mangle]
pub unsafe extern "C" fn read(fd: i32, buf: *mut u8, count: usize) -> isize {
let ret = syscall!(SYS_READ, fd, buf, count);
syscall_ret(ret) as isize
}

/// Write to a file descriptor.
///
/// # Safety
/// `buf` must be a valid pointer to a buffer of at least `count` bytes.
#[no_mangle]
pub unsafe extern "C" fn write(fd: i32, buf: *const u8, count: usize) -> isize {
let ret = syscall!(SYS_WRITE, fd, buf, count);
syscall_ret(ret) as isize
}

/// Close a file descriptor.
#[no_mangle]
pub unsafe extern "C" fn close(fd: i32) -> i32 {
let ret = syscall!(SYS_CLOSE, fd);
syscall_ret(ret) as i32
}

/// Create a hard link.
///
/// # Safety
/// Both path pointers must be valid null-terminated C strings.
#[no_mangle]
pub unsafe extern "C" fn link(oldpath: *const u8, newpath: *const u8) -> i32 {
let ret = syscall!(SYS_LINK, oldpath, newpath);
syscall_ret(ret) as i32
}

/// Remove a file (unlink).
///
/// # Safety
/// `pathname` must be a valid null-terminated C string.
#[no_mangle]
pub unsafe extern "C" fn unlink(pathname: *const u8) -> i32 {
let ret = syscall!(SYS_UNLINK, pathname);
syscall_ret(ret) as i32
}

/// Create a symbolic link.
///
/// # Safety
/// Both path pointers must be valid null-terminated C strings.
#[no_mangle]
pub unsafe extern "C" fn symlink(target: *const u8, linkpath: *const u8) -> i32 {
let ret = syscall!(SYS_SYMLINK, target, linkpath);
syscall_ret(ret) as i32
}

/// Read the target of a symbolic link.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string; `buf` must point to
/// a buffer of at least `bufsiz` bytes.
#[no_mangle]
pub unsafe extern "C" fn readlink(pathname: *const u8, buf: *mut u8, bufsiz: usize) -> isize {
let ret = syscall!(SYS_READLINK, pathname, buf, bufsiz);
syscall_ret(ret) as isize
}

/// Create a directory.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string.
#[no_mangle]
pub unsafe extern "C" fn mkdir(pathname: *const u8, mode: u32) -> i32 {
let ret = syscall!(SYS_MKDIR, pathname, mode);
syscall_ret(ret) as i32
}

/// Remove a directory.
///
/// # Safety
/// `pathname` must be a valid null-terminated C string.
#[no_mangle]
pub unsafe extern "C" fn rmdir(pathname: *const u8) -> i32 {
let ret = syscall!(SYS_RMDIR, pathname);
syscall_ret(ret) as i32
}

/// Rename a file.
///
/// # Safety
/// Both path pointers must be valid null-terminated C strings.
#[no_mangle]
pub unsafe extern "C" fn rename(oldpath: *const u8, newpath: *const u8) -> i32 {
let ret = syscall!(SYS_RENAME, oldpath, newpath);
syscall_ret(ret) as i32
}

/// Get current working directory.
///
/// # Safety
/// `buf` must point to a buffer of at least `size` bytes.
#[no_mangle]
pub unsafe extern "C" fn getcwd(buf: *mut u8, size: usize) -> *mut u8 {
let ret = syscall!(SYS_GETCWD, buf, size);
if ret < 0 {
vibix_abi::errno::ERRNO.set((-ret) as i32);
core::ptr::null_mut()
} else {
buf
}
}

/// Change working directory.
///
/// # Safety
/// `path` must be a valid null-terminated C string.
#[no_mangle]
pub unsafe extern "C" fn chdir(path: *const u8) -> i32 {
let ret = syscall!(SYS_CHDIR, path);
syscall_ret(ret) as i32
}
11 changes: 11 additions & 0 deletions userspace/vibix_libc_defs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "vibix_libc_defs"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
description = "Type definitions and constants for vibix matching the Linux x86_64 ABI layout"

[lib]
name = "vibix_libc_defs"
path = "src/lib.rs"
Loading
Loading