syswonder / ruxos

Rust Unikernel OS
https://ruxos.syswonder.org
Other
59 stars 19 forks source link

Missing syscalls for musl libc #26

Open coolyjg opened 1 year ago

coolyjg commented 1 year ago

This issue is intended to collect problems/requirements/demands for syscalls in rukos when integrating apps. Here, you can add:

coolyjg commented 1 year ago

29 Add renameat, readv, fdatasync. Please note that fsync and fdatasync is not really implemented.

MrRobertYuan commented 11 months ago

For python update openat and add readlinkat First add a struct Directory at fs.rs

pub struct Directory {
    inner: Mutex<axfs::fops::Directory>,
}

impl Directory {
    fn new(inner: axfs::fops::Directory) -> Self {
        Self {
            inner: Mutex::new(inner),
        }
    }

    fn add_to_fd_table(self) -> LinuxResult<c_int> {
        super::fd_ops::add_file_like(Arc::new(self))
    }

    fn from_fd(fd: c_int) -> LinuxResult<Arc<Self>> {
        let f = super::fd_ops::get_file_like(fd)?;
        f.into_any()
            .downcast::<Self>()
            .map_err(|_| LinuxError::EINVAL)
    }
}

impl FileLike for Directory {
    fn read(&self, buf: &mut [u8]) -> LinuxResult<usize> {
        Err(LinuxError::EACCES)
    }

    fn write(&self, buf: &[u8]) -> LinuxResult<usize> {
        Err(LinuxError::EACCES)
    }

    fn stat(&self) -> LinuxResult<ctypes::stat> {
        Err(LinuxError::EACCES)
    }

    fn into_any(self: Arc<Self>) -> Arc<dyn core::any::Any + Send + Sync> {
        self
    }

    fn poll(&self) -> LinuxResult<PollState> {
        Ok(PollState {
            readable: true,
            writable: true,
        })
    }

    fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
        Ok(())
    }
}

modify openat make it can open a dir

/// Open a file under a specific dir
///
///
pub fn sys_openat(_fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mode_t) -> c_int {
    let path = char_ptr_to_str(path);
    debug!("sys_openat <= {:?}, {:#o} {:#o}", path, flags, mode);
    syscall_body!(sys_openat, {
        let options = flags_to_options(flags, mode);
        if (flags as u32) & ctypes::O_DIRECTORY != 0 {
            let dir = axfs::fops::Directory::open_dir(path?, &options)?;
            Directory::new(dir).add_to_fd_table()
        }
        else{
            let file = axfs::fops::File::open(path?, &options)?;
            File::new(file).add_to_fd_table()
        }
    })
}

add readlinkat

/// read value of a symbolic link relative to directory file descriptor
///
/// 
pub fn sys_readlinkat(fd: c_int, pathname: *const c_char, buf: *mut c_char, bufsize: usize) -> usize {
    let path = char_ptr_to_str(pathname);
    debug!("sys_readlinkat <= path = {:?}, fd = {:}, bufsize = {:}", path, fd, bufsize);
    syscall_body!(sys_readlinkat, {
        let mut options = OpenOptions::new();
        options.read(true);
        let dst = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, bufsize as _) };
        // if fd == AT_FDCWD then readat the relative path
        if fd == ctypes::AT_FDCWD as c_int {
            let file = axfs::fops::File::open(path?, &options)?;
            let mut file = File::new(file);
            Ok(file.read(dst)?)
        }
        else{
            let dir = Directory::from_fd(fd)?;
            let mut file = dir.inner.lock().open_file_at(path?, &options)?;
            Ok(file.read(dst)?)
        }
    })
}
minminm commented 11 months ago

For python add getdents64 First add type ino_t, dirent in api/arceos_posix_api/build.rs

fn gen_c_to_rust_bindings(in_file: &str, out_file: &str) {

    let allow_types = [
        "stat",
        "size_t",
        "ssize_t",
        ...
        "ino_t",  // new line
        "dirent", // new line
    ];

    ...
}

Then add sys_getdents64 in fs.rs

type LinuxDirent64 = ctypes::dirent;

fn convert_name_to_array(name: &[u8]) -> [i8; 256] {
    let mut array = [0i8; 256];
    let len = name.len();
    let name_ptr = name.as_ptr() as *const i8;
    let array_ptr = array.as_mut_ptr();

    unsafe {
        core::ptr::copy_nonoverlapping(name_ptr, array_ptr, len);
    }

    array
}

/// Read directory entries from a directory file descriptor.
/// 
/// TODO: check errors
pub unsafe fn sys_getdents64(fd: c_uint, dirent: *mut LinuxDirent64, count: c_uint) -> c_long {
    debug!(
        "sys_getdents64 <= fd: {}, dirent: {:p}, count: {}",
        fd, dirent, count
    );

    syscall_body!(sys_getdents64, {
        let expect_entries = count as usize / 280;        
        let dir = Directory::from_fd(fd as i32)?;
        let mut my_dirent: Vec<DirEntry> = (0..expect_entries).map(|_| DirEntry::default()).collect();

        let n = dir.inner.lock().read_dir(&mut my_dirent)?;       

        for (i, entry) in my_dirent.iter().enumerate() {
            let linux_dirent = LinuxDirent64 {
                d_ino: 1, 
                d_off: 280,
                d_reclen: 280,
                d_type: entry.entry_type() as u8, 
                d_name: convert_name_to_array(&entry.name_as_bytes()), 
            };

            unsafe {
                core::ptr::write(dirent.add(i), linux_dirent);
            }
        }

        Ok(n * 280)
    })
}
Miochyann commented 11 months ago

Missing syscall :SYS_linkat , the system call number is 37

AuYang261 commented 9 months ago

Missing syscall: SYS_getrandom, whose number is 278 in aarch64.

coolyjg commented 8 months ago

Missing syscall: SYS_getrandom, whose number is 278 in aarch64.

Maybe ulib/ruxlibc/src/rand.rs should be put under ruxos-posix-api/

AuYang261 commented 8 months ago

Missing syscall: SYS_preadv, whose number is 69 in aarch64.

AuYang261 commented 8 months ago

Missing the implement of syscall SYS_mremap, which needed by WAMR.

coolyjg commented 8 months ago

Missing the implement of syscall SYS_mremap, which needed by WAMR.

You can use munmap + mmap to do a fake implementation temporarily. True implementation should wait for @ken4647 's work.

coolyjg commented 8 months ago

Previous readlinkat implementation is wrong. Now it is changed to #61

TheSayOL commented 8 months ago

A bug in system call SYS_ppoll: argument timeout could be NULL, and should be checked before using it.

below is new version:

/// `ppoll` used by A64. Currently ignore signal
pub unsafe fn sys_ppoll(
    fds: *mut ctypes::pollfd,
    nfds: ctypes::nfds_t,
    timeout: *const ctypes::timespec,
    _sig_mask: *const ctypes::sigset_t,
    _sig_num: ctypes::size_t,
) -> c_int {
    let to = if timeout.is_null(){
        -1
    } else {
        Duration::from(*timeout).as_millis() as c_int
    };
    debug!("sys_ppoll <= nfds: {} timeout: {:?}", nfds, to);
    sys_poll(fds, nfds, to)
}
TheSayOL commented 7 months ago

missing SYS_kill and SYS_times.

TheSayOL commented 6 months ago

missing SYS_timerfd_create, SYS_timerfd_settime and SYS_timerfd_gettime.