implement a lot fs syscalls without test
This commit is contained in:
parent
3b38c3b75a
commit
7c855d7f5f
@ -9,6 +9,11 @@ pub trait File: Debug + Sync + Send {
|
||||
fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error>;
|
||||
fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error>;
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error>;
|
||||
fn metadata(&self) -> Result<Metadata, Error>;
|
||||
fn set_len(&self, len: u64) -> Result<(), Error>;
|
||||
fn sync_all(&self) -> Result<(), Error>;
|
||||
fn sync_data(&self) -> Result<(), Error>;
|
||||
fn read_entry(&self) -> Result<String, Error>;
|
||||
}
|
||||
|
||||
pub type FileRef = Arc<Box<File>>;
|
||||
@ -72,6 +77,26 @@ impl File for SgxFile {
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.seek(pos)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -307,6 +332,26 @@ impl File for StdoutFile {
|
||||
fn seek(&self, seek_pos: SeekFrom) -> Result<off_t, Error> {
|
||||
Err(Error::new(Errno::ESPIPE, "Stdout does not support seek"))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for StdoutFile {
|
||||
@ -376,6 +421,26 @@ impl File for StdinFile {
|
||||
fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> {
|
||||
Err(Error::new(Errno::EBADF, "Stdin does not support write"))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for StdinFile {
|
||||
|
@ -70,6 +70,40 @@ impl File for INodeFile {
|
||||
};
|
||||
Ok(*offset as i64)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
let metadata = self.inode.metadata()?;
|
||||
Ok(metadata)
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
if !self.options.write {
|
||||
return Err(Error::new(EBADF, "File not writable. Can't set len."));
|
||||
}
|
||||
self.inode.resize(len as usize)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
self.inode.sync()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
// TODO: add sync_data to VFS
|
||||
self.inode.sync()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
if !self.options.read {
|
||||
return Err(Error::new(EBADF, "File not readable. Can't read entry."));
|
||||
}
|
||||
let mut offset = self.offset.lock().unwrap();
|
||||
let name = self.inode.get_entry(*offset)?;
|
||||
*offset += 1;
|
||||
Ok(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl INodeFile {
|
||||
|
@ -12,8 +12,9 @@ pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
|
||||
pub use self::file_table::{FileDesc, FileTable};
|
||||
pub use self::pipe::Pipe;
|
||||
pub use self::inode_file::{INodeFile, ROOT_INODE};
|
||||
use rcore_fs::vfs::{FsError, FileType, INode};
|
||||
use rcore_fs::vfs::{FsError, FileType, INode, Metadata, Timespec};
|
||||
use self::inode_file::OpenOptions;
|
||||
use process::Process;
|
||||
|
||||
// TODO: use the type defined in Rust libc.
|
||||
//
|
||||
@ -87,6 +88,31 @@ pub fn do_readv<'a, 'b>(fd: FileDesc, bufs: &'a mut [&'b mut [u8]]) -> Result<us
|
||||
file_ref.readv(bufs)
|
||||
}
|
||||
|
||||
pub fn do_stat(path: &str) -> Result<Stat, Error> {
|
||||
warn!("stat is partial implemented as lstat");
|
||||
do_lstat(path)
|
||||
}
|
||||
|
||||
pub fn do_fstat(fd: u32) -> Result<Stat, Error> {
|
||||
info!("fstat: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
let stat = Stat::from(file_ref.metadata()?);
|
||||
// TODO: handle symlink
|
||||
Ok(stat)
|
||||
}
|
||||
|
||||
pub fn do_lstat(path: &str) -> Result<Stat, Error> {
|
||||
info!("lstat: path: {}", path);
|
||||
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let inode = current_process.lookup_inode(&path)?;
|
||||
let stat = Stat::from(inode.metadata()?);
|
||||
Ok(stat)
|
||||
}
|
||||
|
||||
pub fn do_lseek<'a, 'b>(fd: FileDesc, offset: SeekFrom) -> Result<off_t, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
@ -94,6 +120,63 @@ pub fn do_lseek<'a, 'b>(fd: FileDesc, offset: SeekFrom) -> Result<off_t, Error>
|
||||
file_ref.seek(offset)
|
||||
}
|
||||
|
||||
pub fn do_fsync(fd: FileDesc) -> Result<(), Error> {
|
||||
info!("fsync: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
file_ref.sync_all()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_fdatasync(fd: FileDesc) -> Result<(), Error> {
|
||||
info!("fdatasync: fd: {}", fd);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
file_ref.sync_data()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_truncate(path: &str, len: usize) -> Result<(), Error> {
|
||||
info!("truncate: path: {:?}, len: {}", path, len);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
current_process.lookup_inode(&path)?.resize(len)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_ftruncate(fd: FileDesc, len: usize) -> Result<(), Error> {
|
||||
info!("ftruncate: fd: {}, len: {}", fd, len);
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
file_ref.set_len(len as u64)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_getdents64(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
info!("getdents64: fd: {}, buf: {:?}, buf_size: {}", fd, buf.as_ptr(), buf.len());
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
let info = file_ref.metadata()?;
|
||||
if info.type_ != FileType::Dir {
|
||||
return Err(Error::new(ENOTDIR, ""));
|
||||
}
|
||||
let mut writer = unsafe { DirentBufWriter::new(buf) };
|
||||
loop {
|
||||
let name = match file_ref.read_entry() {
|
||||
Err(e) if e.errno == ENOENT => break,
|
||||
r => r,
|
||||
}?;
|
||||
// TODO: get ino from dirent
|
||||
let ok = writer.try_write(0, 0, &name);
|
||||
if !ok { break; }
|
||||
}
|
||||
Ok(writer.written_size)
|
||||
}
|
||||
|
||||
pub fn do_close(fd: FileDesc) -> Result<(), Error> {
|
||||
let current_ref = process::get_current();
|
||||
let mut current_process = current_ref.lock().unwrap();
|
||||
@ -160,6 +243,14 @@ extern "C" {
|
||||
fn ocall_sync() -> sgx_status_t;
|
||||
}
|
||||
|
||||
impl Process {
|
||||
fn lookup_inode(&self, path: &str) -> Result<Arc<INode>, Error> {
|
||||
let cwd = self.get_exec_path().split_at(1).1; // skip start '/'
|
||||
let inode = ROOT_INODE.lookup(cwd)?.lookup(path)?;
|
||||
Ok(inode)
|
||||
}
|
||||
}
|
||||
|
||||
/// Split a `path` str to `(base_path, file_name)`
|
||||
fn split_path(path: &str) -> (&str, &str) {
|
||||
let mut split = path.trim_end_matches('/').rsplitn(2, '/');
|
||||
@ -206,3 +297,190 @@ impl OpenFlags {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(packed)] // Don't use 'C'. Or its size will align up to 8 bytes.
|
||||
pub struct LinuxDirent64 {
|
||||
/// Inode number
|
||||
ino: u64,
|
||||
/// Offset to next structure
|
||||
offset: u64,
|
||||
/// Size of this dirent
|
||||
reclen: u16,
|
||||
/// File type
|
||||
type_: u8,
|
||||
/// Filename (null-terminated)
|
||||
name: [u8; 0],
|
||||
}
|
||||
|
||||
struct DirentBufWriter<'a> {
|
||||
buf: &'a mut [u8],
|
||||
rest_size: usize,
|
||||
written_size: usize,
|
||||
}
|
||||
|
||||
impl<'a> DirentBufWriter<'a> {
|
||||
unsafe fn new(buf: &'a mut [u8]) -> Self {
|
||||
let rest_size = buf.len();
|
||||
DirentBufWriter {
|
||||
buf,
|
||||
rest_size,
|
||||
written_size: 0,
|
||||
}
|
||||
}
|
||||
fn try_write(&mut self, inode: u64, type_: u8, name: &str) -> bool {
|
||||
let len = ::core::mem::size_of::<LinuxDirent64>() + name.len() + 1;
|
||||
let len = (len + 7) / 8 * 8; // align up
|
||||
if self.rest_size < len {
|
||||
return false;
|
||||
}
|
||||
let dent = LinuxDirent64 {
|
||||
ino: inode,
|
||||
offset: 0,
|
||||
reclen: len as u16,
|
||||
type_,
|
||||
name: [],
|
||||
};
|
||||
unsafe {
|
||||
let ptr = self.buf.as_mut_ptr().add(self.written_size) as *mut LinuxDirent64;
|
||||
ptr.write(dent);
|
||||
let name_ptr = ptr.add(1) as _;
|
||||
write_cstr(name_ptr, name);
|
||||
}
|
||||
self.rest_size -= len;
|
||||
self.written_size += len;
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Stat {
|
||||
/// ID of device containing file
|
||||
dev: u64,
|
||||
/// inode number
|
||||
ino: u64,
|
||||
/// number of hard links
|
||||
nlink: u64,
|
||||
|
||||
/// file type and mode
|
||||
mode: StatMode,
|
||||
/// user ID of owner
|
||||
uid: u32,
|
||||
/// group ID of owner
|
||||
gid: u32,
|
||||
/// padding
|
||||
_pad0: u32,
|
||||
/// device ID (if special file)
|
||||
rdev: u64,
|
||||
/// total size, in bytes
|
||||
size: u64,
|
||||
/// blocksize for filesystem I/O
|
||||
blksize: u64,
|
||||
/// number of 512B blocks allocated
|
||||
blocks: u64,
|
||||
|
||||
/// last access time
|
||||
atime: Timespec,
|
||||
/// last modification time
|
||||
mtime: Timespec,
|
||||
/// last status change time
|
||||
ctime: Timespec,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct StatMode: u32 {
|
||||
const NULL = 0;
|
||||
/// Type
|
||||
const TYPE_MASK = 0o170000;
|
||||
/// FIFO
|
||||
const FIFO = 0o010000;
|
||||
/// character device
|
||||
const CHAR = 0o020000;
|
||||
/// directory
|
||||
const DIR = 0o040000;
|
||||
/// block device
|
||||
const BLOCK = 0o060000;
|
||||
/// ordinary regular file
|
||||
const FILE = 0o100000;
|
||||
/// symbolic link
|
||||
const LINK = 0o120000;
|
||||
/// socket
|
||||
const SOCKET = 0o140000;
|
||||
|
||||
/// Set-user-ID on execution.
|
||||
const SET_UID = 0o4000;
|
||||
/// Set-group-ID on execution.
|
||||
const SET_GID = 0o2000;
|
||||
|
||||
/// Read, write, execute/search by owner.
|
||||
const OWNER_MASK = 0o700;
|
||||
/// Read permission, owner.
|
||||
const OWNER_READ = 0o400;
|
||||
/// Write permission, owner.
|
||||
const OWNER_WRITE = 0o200;
|
||||
/// Execute/search permission, owner.
|
||||
const OWNER_EXEC = 0o100;
|
||||
|
||||
/// Read, write, execute/search by group.
|
||||
const GROUP_MASK = 0o70;
|
||||
/// Read permission, group.
|
||||
const GROUP_READ = 0o40;
|
||||
/// Write permission, group.
|
||||
const GROUP_WRITE = 0o20;
|
||||
/// Execute/search permission, group.
|
||||
const GROUP_EXEC = 0o10;
|
||||
|
||||
/// Read, write, execute/search by others.
|
||||
const OTHER_MASK = 0o7;
|
||||
/// Read permission, others.
|
||||
const OTHER_READ = 0o4;
|
||||
/// Write permission, others.
|
||||
const OTHER_WRITE = 0o2;
|
||||
/// Execute/search permission, others.
|
||||
const OTHER_EXEC = 0o1;
|
||||
}
|
||||
}
|
||||
|
||||
impl StatMode {
|
||||
fn from_type_mode(type_: FileType, mode: u16) -> Self {
|
||||
let type_ = match type_ {
|
||||
FileType::File => StatMode::FILE,
|
||||
FileType::Dir => StatMode::DIR,
|
||||
FileType::SymLink => StatMode::LINK,
|
||||
FileType::CharDevice => StatMode::CHAR,
|
||||
FileType::BlockDevice => StatMode::BLOCK,
|
||||
FileType::Socket => StatMode::SOCKET,
|
||||
FileType::NamedPipe => StatMode::FIFO,
|
||||
_ => StatMode::NULL,
|
||||
};
|
||||
let mode = StatMode::from_bits_truncate(mode as u32);
|
||||
type_ | mode
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Metadata> for Stat {
|
||||
fn from(info: Metadata) -> Self {
|
||||
Stat {
|
||||
dev: info.dev as u64,
|
||||
ino: info.inode as u64,
|
||||
mode: StatMode::from_type_mode(info.type_, info.mode as u16),
|
||||
nlink: info.nlinks as u64,
|
||||
uid: info.uid as u32,
|
||||
gid: info.gid as u32,
|
||||
rdev: 0,
|
||||
size: info.size as u64,
|
||||
blksize: info.blk_size as u64,
|
||||
blocks: info.blocks as u64,
|
||||
atime: info.atime,
|
||||
mtime: info.mtime,
|
||||
ctime: info.ctime,
|
||||
_pad0: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a Rust string to C string
|
||||
pub unsafe fn write_cstr(ptr: *mut u8, s: &str) {
|
||||
ptr.copy_from(s.as_ptr(), s.len());
|
||||
ptr.add(s.len()).write(0);
|
||||
}
|
||||
|
@ -77,6 +77,26 @@ impl File for PipeReader {
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
Err(Error::new(Errno::ESPIPE, "Pipe does not support seek"))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for PipeReader {}
|
||||
@ -128,6 +148,26 @@ impl File for PipeWriter {
|
||||
fn seek(&self, seek_pos: SeekFrom) -> Result<off_t, Error> {
|
||||
Err(Error::new(Errno::ESPIPE, "Pipe does not support seek"))
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_len(&self, len: u64) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_all(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sync_data(&self) -> Result<(), Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read_entry(&self) -> Result<String, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for PipeWriter {}
|
||||
|
@ -34,7 +34,15 @@ pub extern "C" fn dispatch_syscall(
|
||||
SYS_write => do_write(arg0 as FileDesc, arg1 as *const u8, arg2 as usize),
|
||||
SYS_readv => do_readv(arg0 as FileDesc, arg1 as *mut iovec_t, arg2 as i32),
|
||||
SYS_writev => do_writev(arg0 as FileDesc, arg1 as *mut iovec_t, arg2 as i32),
|
||||
SYS_stat => do_stat(arg0 as *const i8, arg1 as *mut fs::Stat),
|
||||
SYS_fstat => do_fstat(arg0 as FileDesc, arg1 as *mut fs::Stat),
|
||||
SYS_lstat => do_lstat(arg0 as *const i8, arg1 as *mut fs::Stat),
|
||||
SYS_lseek => do_lseek(arg0 as FileDesc, arg1 as off_t, arg2 as i32),
|
||||
SYS_fsync => do_fsync(arg0 as FileDesc),
|
||||
SYS_fdatasync => do_fdatasync(arg0 as FileDesc),
|
||||
SYS_truncate => do_truncate(arg0 as *const i8, arg1 as usize),
|
||||
SYS_ftruncate => do_ftruncate(arg0 as FileDesc, arg1 as usize),
|
||||
SYS_getdents64 => do_getdents64(arg0 as FileDesc, arg1 as *mut u8, arg2 as usize),
|
||||
SYS_sync => do_sync(),
|
||||
SYS_getcwd => do_getcwd(arg0 as *mut u8, arg1 as usize),
|
||||
|
||||
@ -159,8 +167,8 @@ fn do_spawn(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_open(path_buf: *const i8, flags: u32, mode: u32) -> Result<isize, Error> {
|
||||
let path = unsafe { CStr::from_ptr(path_buf).to_string_lossy().into_owned() };
|
||||
fn do_open(path: *const i8, flags: u32, mode: u32) -> Result<isize, Error> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
let fd = fs::do_open(&path, flags, mode)?;
|
||||
Ok(fd as isize)
|
||||
}
|
||||
@ -238,6 +246,32 @@ fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result<isize, Error>
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
check_mut_ptr(stat_buf)?;
|
||||
|
||||
let stat = fs::do_stat(&path)?;
|
||||
unsafe { stat_buf.write(stat); }
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_fstat(fd: FileDesc, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
check_mut_ptr(stat_buf)?;
|
||||
|
||||
let stat = fs::do_fstat(fd)?;
|
||||
unsafe { stat_buf.write(stat); }
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_lstat(path: *const i8, stat_buf: *mut fs::Stat) -> Result<isize, Error> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
check_mut_ptr(stat_buf)?;
|
||||
|
||||
let stat = fs::do_lstat(&path)?;
|
||||
unsafe { stat_buf.write(stat); }
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result<isize, Error> {
|
||||
let seek_from = match whence {
|
||||
0 => {
|
||||
@ -264,6 +298,36 @@ fn do_lseek(fd: FileDesc, offset: off_t, whence: i32) -> Result<isize, Error> {
|
||||
Ok(offset as isize)
|
||||
}
|
||||
|
||||
fn do_fsync(fd: FileDesc) -> Result<isize, Error> {
|
||||
fs::do_fsync(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_fdatasync(fd: FileDesc) -> Result<isize, Error> {
|
||||
fs::do_fdatasync(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_truncate(path: *const i8, len: usize) -> Result<isize, Error> {
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
fs::do_truncate(&path, len)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_ftruncate(fd: FileDesc, len: usize) -> Result<isize, Error> {
|
||||
fs::do_ftruncate(fd, len)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn do_getdents64(fd: FileDesc, buf: *mut u8, buf_size: usize) -> Result<isize, Error> {
|
||||
let safe_buf = {
|
||||
check_mut_array(buf, buf_size)?;
|
||||
unsafe { std::slice::from_raw_parts_mut(buf, buf_size) }
|
||||
};
|
||||
let len = fs::do_getdents64(fd, safe_buf)?;
|
||||
Ok(len as isize)
|
||||
}
|
||||
|
||||
fn do_sync() -> Result<isize, Error> {
|
||||
fs::do_sync()?;
|
||||
Ok(0)
|
||||
|
Loading…
Reference in New Issue
Block a user