use crate::{
capi::{
ret::IntoCReturn,
utils::{self, CBorrowedFd},
},
error::{Error, ErrorImpl},
flags::{OpenFlags, RenameFlags},
procfs::ProcfsHandle,
utils::FdExt,
InodeType, Root, RootRef,
};
use std::{
fs::Permissions,
os::unix::{fs::PermissionsExt, io::RawFd},
};
use libc::{c_char, c_int, c_uint, dev_t, size_t};
#[no_mangle]
pub unsafe extern "C" fn pathrs_open_root(path: *const c_char) -> RawFd {
unsafe { utils::parse_path(path) } .and_then(Root::open)
.into_c_return()
}
utils::symver! {
fn pathrs_open_root <- (pathrs_open_root, version = "LIBPATHRS_0.2", default);
fn pathrs_open_root <- (pathrs_root_open, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub extern "C" fn pathrs_reopen(fd: CBorrowedFd<'_>, flags: c_int) -> RawFd {
let flags = OpenFlags::from_bits_retain(flags);
|| -> Result<_, Error> {
fd.try_as_borrowed_fd()?
.reopen(&ProcfsHandle::new()?, flags)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_reopen <- (pathrs_reopen, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_resolve(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
) -> RawFd {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; root.resolve(path)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_resolve <- (pathrs_inroot_resolve, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_resolve <- (pathrs_resolve, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_resolve_nofollow(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
) -> RawFd {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; root.resolve_nofollow(path)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_resolve_nofollow <- (pathrs_inroot_resolve_nofollow, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_resolve_nofollow <- (pathrs_resolve_nofollow, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_open(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
flags: c_int,
) -> RawFd {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; let flags = OpenFlags::from_bits_retain(flags);
root.open_subpath(path, flags)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_open <- (pathrs_inroot_open, version = "LIBPATHRS_0.2", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_readlink(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
linkbuf: *mut c_char,
linkbuf_size: size_t,
) -> RawFd {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; let link_target = root.readlink(path)?;
unsafe { utils::copy_path_into_buffer(link_target, linkbuf, linkbuf_size) }
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_readlink <- (pathrs_inroot_readlink, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_readlink <- (pathrs_readlink, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_rename(
root_fd: CBorrowedFd<'_>,
src: *const c_char,
dst: *const c_char,
flags: u32,
) -> c_int {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let src = unsafe { utils::parse_path(src) }?; let dst = unsafe { utils::parse_path(dst) }?;
let rflags = RenameFlags::from_bits_retain(flags);
root.rename(src, dst, rflags)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_rename <- (pathrs_inroot_rename, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_rename <- (pathrs_rename, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_rmdir(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
) -> c_int {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; root.remove_dir(path)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_rmdir <- (pathrs_inroot_rmdir, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_rmdir <- (pathrs_rmdir, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_unlink(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
) -> c_int {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; root.remove_file(path)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_unlink <- (pathrs_inroot_unlink, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_unlink <- (pathrs_unlink, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_remove_all(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
) -> c_int {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; root.remove_all(path)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_remove_all <- (pathrs_inroot_remove_all, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_remove_all <- (pathrs_remove_all, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_creat(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
flags: c_int,
mode: c_uint,
) -> RawFd {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; let mode = mode & !libc::S_IFMT;
let perm = Permissions::from_mode(mode);
root.create_file(path, OpenFlags::from_bits_retain(flags), &perm)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_creat <- (pathrs_inroot_creat, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_creat <- (pathrs_creat, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_mkdir(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
mode: c_uint,
) -> c_int {
let mode = mode & !libc::S_IFMT;
pathrs_inroot_mknod(root_fd, path, libc::S_IFDIR | mode, 0)
}
utils::symver! {
fn pathrs_inroot_mkdir <- (pathrs_inroot_mkdir, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_mkdir <- (pathrs_mkdir, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_mkdir_all(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
mode: c_uint,
) -> RawFd {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path) }?; let perm = Permissions::from_mode(mode);
root.mkdir_all(path, &perm)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_mkdir_all <- (pathrs_inroot_mkdir_all, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_mkdir_all <- (pathrs_mkdir_all, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_mknod(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
mode: c_uint,
dev: dev_t,
) -> c_int {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path)? };
let fmt = mode & libc::S_IFMT;
let perms = Permissions::from_mode(mode ^ fmt);
let inode_type = match fmt {
libc::S_IFREG => InodeType::File(perms),
libc::S_IFDIR => InodeType::Directory(perms),
libc::S_IFBLK => InodeType::BlockDevice(perms, dev),
libc::S_IFCHR => InodeType::CharacterDevice(perms, dev),
libc::S_IFIFO => InodeType::Fifo(perms),
libc::S_IFSOCK => Err(ErrorImpl::NotImplemented {
feature: "mknod(S_IFSOCK)".into(),
})?,
_ => Err(ErrorImpl::InvalidArgument {
name: "mode".into(),
description: "invalid S_IFMT mask".into(),
})?,
};
root.create(path, &inode_type)
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_mknod <- (pathrs_inroot_mknod, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_mknod <- (pathrs_mknod, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_symlink(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
target: *const c_char,
) -> c_int {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path)? }; let target = unsafe { utils::parse_path(target)? }; root.create(path, &InodeType::Symlink(target.into()))
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_symlink <- (pathrs_inroot_symlink, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_symlink <- (pathrs_symlink, version = "LIBPATHRS_0.1", default);
}
#[no_mangle]
pub unsafe extern "C" fn pathrs_inroot_hardlink(
root_fd: CBorrowedFd<'_>,
path: *const c_char,
target: *const c_char,
) -> c_int {
|| -> Result<_, Error> {
let root_fd = root_fd.try_as_borrowed_fd()?;
let root = RootRef::from_fd(root_fd);
let path = unsafe { utils::parse_path(path)? }; let target = unsafe { utils::parse_path(target)? }; root.create(path, &InodeType::Hardlink(target.into()))
}()
.into_c_return()
}
utils::symver! {
fn pathrs_inroot_hardlink <- (pathrs_inroot_hardlink, version = "LIBPATHRS_0.2", default);
fn pathrs_inroot_hardlink <- (pathrs_hardlink, version = "LIBPATHRS_0.1", default);
}