syswonder / ruxos

Rust Unikernel OS
https://ruxos.syswonder.org
Other
45 stars 15 forks source link

Missing syscalls for musl libc #26

Open coolyjg opened 7 months ago

coolyjg commented 7 months ago

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

coolyjg commented 7 months ago

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

MrRobertYuan commented 7 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 7 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 7 months ago

Missing syscall :SYS_linkat , the system call number is 37

AuYang261 commented 4 months ago

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

coolyjg commented 4 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 4 months ago

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

AuYang261 commented 4 months ago

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

coolyjg commented 4 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 4 months ago

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

TheSayOL commented 3 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 3 months ago

missing SYS_kill and SYS_times.

TheSayOL commented 1 month ago

missing SYS_timerfd_create, SYS_timerfd_settime and SYS_timerfd_gettime.