Add /dev/zero, /dev/random, /dev/urandom, and /dev/arandom
This commit is contained in:
parent
8cda63ab3a
commit
8686322afb
@ -1,35 +1,35 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NullFile;
|
pub struct DevNull;
|
||||||
|
|
||||||
impl File for NullFile {
|
|
||||||
fn read(&self, _buf: &mut [u8]) -> Result<usize, Error> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
impl File for DevNull {
|
||||||
fn write(&self, _buf: &[u8]) -> Result<usize, Error> {
|
fn write(&self, _buf: &[u8]) -> Result<usize, Error> {
|
||||||
Ok(0)
|
Ok(_buf.len())
|
||||||
}
|
|
||||||
|
|
||||||
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, Error> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize, Error> {
|
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize, Error> {
|
||||||
unimplemented!()
|
Ok(_buf.len())
|
||||||
}
|
|
||||||
|
|
||||||
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||||
unimplemented!()
|
Ok(bufs.iter().map(|buf| buf.len()).sum())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&self, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support reads")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support reads")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support reads")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||||
unimplemented!()
|
errno!(EINVAL, "device not support seeks")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&self) -> Result<Metadata, Error> {
|
fn metadata(&self) -> Result<Metadata, Error> {
|
||||||
@ -37,19 +37,19 @@ impl File for NullFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||||
unimplemented!()
|
errno!(EINVAL, "device not support resizing")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_all(&self) -> Result<(), Error> {
|
fn sync_all(&self) -> Result<(), Error> {
|
||||||
unimplemented!()
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_data(&self) -> Result<(), Error> {
|
fn sync_data(&self) -> Result<(), Error> {
|
||||||
unimplemented!()
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_entry(&self) -> Result<String, Error> {
|
fn read_entry(&self) -> Result<String, Error> {
|
||||||
unimplemented!()
|
errno!(ENOTDIR, "device is not a directory")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &Any {
|
fn as_any(&self) -> &Any {
|
84
src/libos/src/fs/dev_random.rs
Normal file
84
src/libos/src/fs/dev_random.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DevRandom;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn sgx_read_rand(rand_buf: *mut u8, buf_size: usize) -> sgx_status_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File for DevRandom {
|
||||||
|
fn read(&self, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
let buf = _buf.as_mut_ptr();
|
||||||
|
let size = _buf.len();
|
||||||
|
let status = unsafe { sgx_read_rand(buf, size) };
|
||||||
|
if status != sgx_status_t::SGX_SUCCESS {
|
||||||
|
return errno!(EAGAIN, "failed to get random number from sgx");
|
||||||
|
}
|
||||||
|
Ok(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
self.read(_buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||||
|
let mut total_nbytes = 0;
|
||||||
|
for buf in bufs {
|
||||||
|
match self.read(buf) {
|
||||||
|
Ok(this_nbytes) => {
|
||||||
|
total_nbytes += this_nbytes;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
if total_nbytes > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(total_nbytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, _buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support writes")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support writes")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support writes")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||||
|
errno!(EINVAL, "device not support seeks")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn metadata(&self) -> Result<Metadata, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||||
|
errno!(EINVAL, "device not support resizing")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_all(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_data(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_entry(&self) -> Result<String, Error> {
|
||||||
|
errno!(ENOTDIR, "device is not a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
65
src/libos/src/fs/dev_zero.rs
Normal file
65
src/libos/src/fs/dev_zero.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DevZero;
|
||||||
|
|
||||||
|
impl File for DevZero {
|
||||||
|
fn read(&self, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
for b in _buf.iter_mut() {
|
||||||
|
*b = 0;
|
||||||
|
}
|
||||||
|
Ok(_buf.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
self.read(_buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn readv(&self, bufs: &mut [&mut [u8]]) -> Result<usize, Error> {
|
||||||
|
let mut total_nbytes = 0;
|
||||||
|
for buf in bufs {
|
||||||
|
total_nbytes += self.read(buf)?;
|
||||||
|
}
|
||||||
|
Ok(total_nbytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&self, _buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support writes")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support writes")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writev(&self, bufs: &[&[u8]]) -> Result<usize, Error> {
|
||||||
|
errno!(EINVAL, "device not support writes")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||||
|
errno!(EINVAL, "device not support seeks")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn metadata(&self) -> Result<Metadata, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||||
|
errno!(EINVAL, "device not support resizing")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_all(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_data(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_entry(&self) -> Result<String, Error> {
|
||||||
|
errno!(ENOTDIR, "device is not a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,9 @@ pub use self::file_table::{FileDesc, FileTable};
|
|||||||
use self::inode_file::OpenOptions;
|
use self::inode_file::OpenOptions;
|
||||||
pub use self::inode_file::{INodeExt, INodeFile, ROOT_INODE};
|
pub use self::inode_file::{INodeExt, INodeFile, ROOT_INODE};
|
||||||
pub use self::io_multiplexing::*;
|
pub use self::io_multiplexing::*;
|
||||||
use self::null::NullFile;
|
use self::dev_null::DevNull;
|
||||||
|
use self::dev_zero::DevZero;
|
||||||
|
use self::dev_random::DevRandom;
|
||||||
pub use self::pipe::Pipe;
|
pub use self::pipe::Pipe;
|
||||||
pub use self::socket_file::{AsSocket, SocketFile};
|
pub use self::socket_file::{AsSocket, SocketFile};
|
||||||
pub use self::unix_socket::{AsUnixSocket, UnixSocketFile};
|
pub use self::unix_socket::{AsUnixSocket, UnixSocketFile};
|
||||||
@ -25,7 +27,9 @@ mod file_table;
|
|||||||
mod hostfs;
|
mod hostfs;
|
||||||
mod inode_file;
|
mod inode_file;
|
||||||
mod io_multiplexing;
|
mod io_multiplexing;
|
||||||
mod null;
|
mod dev_null;
|
||||||
|
mod dev_zero;
|
||||||
|
mod dev_random;
|
||||||
mod pipe;
|
mod pipe;
|
||||||
mod sgx_impl;
|
mod sgx_impl;
|
||||||
mod socket_file;
|
mod socket_file;
|
||||||
@ -410,7 +414,13 @@ impl Process {
|
|||||||
/// Open a file on the process. But DO NOT add it to file table.
|
/// Open a file on the process. But DO NOT add it to file table.
|
||||||
pub fn open_file(&self, path: &str, flags: OpenFlags, mode: u32) -> Result<Box<File>, Error> {
|
pub fn open_file(&self, path: &str, flags: OpenFlags, mode: u32) -> Result<Box<File>, Error> {
|
||||||
if path == "/dev/null" {
|
if path == "/dev/null" {
|
||||||
return Ok(Box::new(NullFile));
|
return Ok(Box::new(DevNull));
|
||||||
|
}
|
||||||
|
if path == "/dev/zero" {
|
||||||
|
return Ok(Box::new(DevZero));
|
||||||
|
}
|
||||||
|
if path == "/dev/random" || path == "/dev/urandom" || path == "/dev/arandom" {
|
||||||
|
return Ok(Box::new(DevRandom));
|
||||||
}
|
}
|
||||||
let inode = if flags.contains(OpenFlags::CREATE) {
|
let inode = if flags.contains(OpenFlags::CREATE) {
|
||||||
let (dir_path, file_name) = split_path(&path);
|
let (dir_path, file_name) = split_path(&path);
|
||||||
|
@ -4,8 +4,9 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../)
|
|||||||
# Dependencies: need to be compiled but not to run by any Makefile target
|
# Dependencies: need to be compiled but not to run by any Makefile target
|
||||||
TEST_DEPS := dev_null
|
TEST_DEPS := dev_null
|
||||||
# Tests: need to be compiled and run by test-% target
|
# Tests: need to be compiled and run by test-% target
|
||||||
#TESTS := empty argv hello_world malloc mmap file getpid spawn pipe time truncate readdir mkdir link tls pthread uname rlimit client server server_epoll unix_socket cout hostfs cpuid rdtsc
|
TESTS := empty argv hello_world malloc mmap file getpid spawn pipe time \
|
||||||
TESTS := hello_world file readdir mkdir link hostfs
|
truncate readdir mkdir link tls pthread uname rlimit client server \
|
||||||
|
server_epoll unix_socket cout hostfs cpuid rdtsc device
|
||||||
# Benchmarks: need to be compiled and run by bench-% target
|
# Benchmarks: need to be compiled and run by bench-% target
|
||||||
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
||||||
|
|
||||||
|
5
test/device/Makefile
Normal file
5
test/device/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS :=
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
91
test/device/main.c
Normal file
91
test/device/main.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test utilities
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int check_file_readable(const char* filename) {
|
||||||
|
int fd;
|
||||||
|
char buf[512] = {0};
|
||||||
|
int len;
|
||||||
|
if ((fd = open(filename, O_RDONLY)) < 0) {
|
||||||
|
throw_error("failed to open the file");
|
||||||
|
}
|
||||||
|
if ((len = read(fd, buf, sizeof(buf))) != sizeof(buf)) {
|
||||||
|
throw_error("failed to read the file");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_file_writable(const char* filename) {
|
||||||
|
int fd;
|
||||||
|
char buf[512] = {0};
|
||||||
|
int len;
|
||||||
|
if ((fd = open(filename, O_WRONLY)) < 0) {
|
||||||
|
throw_error("failed to open the file");
|
||||||
|
}
|
||||||
|
if ((len = write(fd, buf, sizeof(buf))) != sizeof(buf)) {
|
||||||
|
throw_error("failed to read the file");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for /dev/random, /dev/urandom, /dev/
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
int test_dev_null() {
|
||||||
|
if (check_file_writable("/dev/null")) {
|
||||||
|
throw_error("failed to write to /dev/null");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_dev_zero() {
|
||||||
|
if (check_file_readable("/dev/zero")) {
|
||||||
|
throw_error("failed to read from /dev/null");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_dev_random() {
|
||||||
|
if (check_file_readable("/dev/random")) {
|
||||||
|
throw_error("failed to read from /dev/random");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_dev_urandom() {
|
||||||
|
if (check_file_readable("/dev/urandom")) {
|
||||||
|
throw_error("failed to read from /dev/urandom");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_dev_arandom() {
|
||||||
|
if (check_file_readable("/dev/arandom")) {
|
||||||
|
throw_error("failed to read from /dev/arandom");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test suite
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static test_case_t test_cases[] = {
|
||||||
|
TEST_CASE(test_dev_null),
|
||||||
|
TEST_CASE(test_dev_zero),
|
||||||
|
TEST_CASE(test_dev_random),
|
||||||
|
TEST_CASE(test_dev_urandom),
|
||||||
|
TEST_CASE(test_dev_arandom),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user