shitbox/unistd/src/lib.rs

161 lines
3.7 KiB
Rust

#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
use errno::Errno;
use libc::utsname;
use sc::syscall;
use std::{error::Error, ffi::CString, fs::File, os::fd::AsRawFd, ptr, u8};
fn new_utsname() -> utsname {
utsname {
sysname: [0; 65],
nodename: [0; 65],
release: [0; 65],
version: [0; 65],
machine: [0; 65],
domainname: [0; 65],
}
}
pub fn ftruncate(fd: &File, len: i64) -> Result<(), Box<dyn Error>> {
let ret = unsafe { syscall!(FTRUNCATE, fd.as_raw_fd(), len) };
if ret == 0 {
Ok(())
} else {
Err(Errno::from(ret).into())
}
}
pub fn truncate(path: &str, len: i64) -> Result<(), Box<dyn Error>> {
let ret = unsafe { syscall!(TRUNCATE, CString::new(path)?.as_ptr(), len) };
if ret == 0 {
Ok(())
} else {
Err(Errno::from(ret).into())
}
}
#[allow(clippy::cast_sign_loss)]
pub fn gethostname() -> Result<String, Box<dyn Error>> {
let mut uts = new_utsname();
unsafe {
let ret = syscall!(UNAME, ptr::addr_of_mut!(uts));
if ret != 0 {
return Err(Errno::from(ret).into());
}
}
let name = uts
.nodename
.iter()
.map(|x| *x as u8)
.take_while(|x| *x != 0)
.collect();
String::from_utf8(name).map_err(Into::into)
}
pub fn sethostname(name: &str) -> Result<(), Errno> {
let ret = unsafe { syscall!(SETHOSTNAME, name.as_ptr(), name.len()) };
if ret == 0 {
Ok(())
} else {
Err(ret.into())
}
}
pub fn link(source: &str, dest: &str) -> Result<(), Box<dyn Error>> {
let ret = unsafe {
syscall!(
LINKAT,
libc::AT_FDCWD,
CString::new(source)?.as_ptr(),
libc::AT_FDCWD,
CString::new(dest)?.as_ptr(),
0
)
};
if ret == 0 {
Ok(())
} else {
Err(Errno::from(ret).into())
}
}
pub fn unlink(name: &str) -> Result<(), Box<dyn Error>> {
let ret = unsafe { syscall!(UNLINKAT, libc::AT_FDCWD, CString::new(name)?.as_ptr(), 0) };
if ret == 0 {
Ok(())
} else {
Err(Errno::from(ret).into())
}
}
#[allow(clippy::cast_sign_loss)]
pub fn readlink(name: &str) -> Result<String, Box<dyn Error>> {
let mut buf = Vec::<i8>::with_capacity(1024);
let ret = unsafe {
syscall!(
READLINKAT,
libc::AT_FDCWD,
CString::new(name)?.as_ptr(),
buf.as_mut_ptr(),
1024
)
};
if ret == 0 {
let path = buf
.iter()
.map(|x| *x as u8)
.take_while(|x| *x != 0)
.collect();
String::from_utf8(path).map_err(Into::into)
} else {
Err(Errno::from(ret).into())
}
}
pub fn fdatasync(fd: &File) -> Result<(), Errno> {
let ret = unsafe { syscall!(FDATASYNC, fd.as_raw_fd()) };
if ret == 0 {
Ok(())
} else {
Err(ret.into())
}
}
pub fn syncfs(fd: &File) -> Result<(), Errno> {
let ret = unsafe { syscall!(SYNCFS, fd.as_raw_fd()) };
if ret == 0 {
Ok(())
} else {
Err(ret.into())
}
}
pub fn fsync(fd: &File) -> Result<(), Errno> {
let ret = unsafe { syscall!(FSYNC, fd.as_raw_fd()) };
if ret == 0 {
Ok(())
} else {
Err(ret.into())
}
}
pub fn sync() {
unsafe { syscall!(SYNC) };
}
pub fn symlink(source: &str, dest: &str) -> Result<(), Box<dyn Error>> {
let ret = unsafe {
syscall!(
SYMLINKAT,
CString::new(source)?.as_ptr(),
libc::AT_FDCWD,
CString::new(dest)?.as_ptr()
)
};
if ret == 0 {
Ok(())
} else {
Err(Errno::from(ret).into())
}
}