lrs-lang / lib

An experimental standard library
Mozilla Public License 2.0
224 stars 3 forks source link

Add an abstraction layer above the syscall layer #26

Open mahkoh opened 8 years ago

mahkoh commented 8 years ago

The following crates are part of the syscall layer:

cty

This crate contains C types used by the kernel in its public interfaces. For example,

#[repr(C)]
#[derive(Pod, Eq)]
pub struct sockaddr_in6 {
    pub sin6_family:   c_ushort,
    pub sin6_port:     __be16,
    pub sin6_flowinfo: __be32,
    pub sin6_addr:     in6_addr,
    pub sin6_scope_id: __u32,
}
r_syscall

This crate contain the raw syscall interface of the kernel. It contains one-line functions that immediately execute the syscall assembly. Their signature mirrors the kernel's syscall signature. For example:

pub unsafe fn openat(dfd: k_int, filename: *const c_char, flags: k_int,
                     mode: umode_t) -> k_int {
    call!(cty::__NR_openat, dfd, filename, flags, mode) as k_int
}
syscall

This crate wraps the unsafe r_syscall functions in safe functions. For example:

pub fn openat(dir: c_int, path: &CStr, mut flags: c_int, mode: umode_t) -> c_int {
    if cfg!(not(no_auto_cloexec)) {
        flags |= O_CLOEXEC;
    }
    flags |= O_LARGEFILE;
    unsafe { r::openat(dir, path.as_ptr(), flags, mode) }
}

The syscall crate is then used directly by the crates above it. For example, in the file crate:

    pub fn rel_open<P>(&self, path: P, flags: FileFlags, mode: Mode) -> Result<File>
        where P: ToCString,
    {
        let mut buf: [u8; PATH_MAX] = unsafe { mem::uninit() };
        let path: Rmo<_, FbHeap> = try!(path.rmo_cstr(&mut buf));
        let fd = match retry(|| openat(self.fd, &path, flags.0, mode.0)) {
            Ok(fd) => fd,
            // Due to a bug in the kernel, open returns WrongDeviceType instead of
            // NoSuchDevice.
            Err(error::WrongDeviceType) => return Err(error::NoSuchDevice),
            Err(e) => return Err(e),
        };
        Ok(File {
            fd: fd,
            owned: true,
        })
    }
The new layer

I've come to believe that this is wrong. There should be an additional layer between the syscalls and the other crates. This layer would, for example, perform the Pascal string -> C string conversion. Apart from this, it would mostly be pass-through on linux.

On other systems, however, it would perform certain translations. This would allow us to port lrs to other platforms such as redox much more easily.