[libos] Add support for UTIME
This commit is contained in:
parent
66d1ebe918
commit
4fab368127
@ -29,6 +29,9 @@ pub use self::stat::{do_fstat, do_fstatat, Stat, StatFlags};
|
|||||||
pub use self::symlink::{do_readlinkat, do_symlinkat};
|
pub use self::symlink::{do_readlinkat, do_symlinkat};
|
||||||
pub use self::truncate::{do_ftruncate, do_truncate};
|
pub use self::truncate::{do_ftruncate, do_truncate};
|
||||||
pub use self::unlink::{do_unlinkat, UnlinkFlags};
|
pub use self::unlink::{do_unlinkat, UnlinkFlags};
|
||||||
|
pub use self::utimes::{
|
||||||
|
do_utimes_fd, do_utimes_path, get_utimes, utimbuf_t, Utime, UtimeFlags, UTIME_OMIT,
|
||||||
|
};
|
||||||
pub use self::write::{do_pwrite, do_write, do_writev};
|
pub use self::write::{do_pwrite, do_write, do_writev};
|
||||||
|
|
||||||
mod access;
|
mod access;
|
||||||
@ -56,4 +59,5 @@ mod stat;
|
|||||||
mod symlink;
|
mod symlink;
|
||||||
mod truncate;
|
mod truncate;
|
||||||
mod unlink;
|
mod unlink;
|
||||||
|
mod utimes;
|
||||||
mod write;
|
mod write;
|
||||||
|
138
src/libos/src/fs/file_ops/utimes.rs
Normal file
138
src/libos/src/fs/file_ops/utimes.rs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
use crate::util::mem_util::from_user;
|
||||||
|
|
||||||
|
use super::time::{timespec_t, OcclumTimeProvider};
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use rcore_fs::dev::TimeProvider;
|
||||||
|
|
||||||
|
const UTIME_NOW: i64 = (1i64 << 30) - 1i64;
|
||||||
|
pub const UTIME_OMIT: i64 = (1i64 << 30) - 2i64;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct UtimeFlags: i32 {
|
||||||
|
const AT_SYMLINK_NOFOLLOW = 1 << 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub struct utimbuf_t {
|
||||||
|
atime: time_t,
|
||||||
|
mtime: time_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl utimbuf_t {
|
||||||
|
pub fn atime(&self) -> time_t {
|
||||||
|
self.atime
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mtime(&self) -> time_t {
|
||||||
|
self.mtime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum Utime {
|
||||||
|
UTIME_OMIT,
|
||||||
|
UTIME_NOW,
|
||||||
|
UTIME(Timespec),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_utimes(times: Option<(timespec_t, timespec_t)>) -> Result<(Utime, Utime)> {
|
||||||
|
let now = OcclumTimeProvider.current_time();
|
||||||
|
if let Some(times) = times {
|
||||||
|
let (atime, mtime) = times;
|
||||||
|
|
||||||
|
if (!timespec_valid(atime)) || (!timespec_valid(mtime)) {
|
||||||
|
return_errno!(EINVAL, "parameter: times is invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
let atime = if atime.nsec() == UTIME_OMIT {
|
||||||
|
Utime::UTIME_OMIT
|
||||||
|
} else if atime.nsec() == UTIME_NOW {
|
||||||
|
Utime::UTIME(now)
|
||||||
|
} else {
|
||||||
|
Utime::UTIME(Timespec {
|
||||||
|
sec: atime.sec(),
|
||||||
|
nsec: atime.nsec(),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let mtime = if mtime.nsec() == UTIME_OMIT {
|
||||||
|
Utime::UTIME_OMIT
|
||||||
|
} else if mtime.nsec() == UTIME_NOW {
|
||||||
|
Utime::UTIME(now)
|
||||||
|
} else {
|
||||||
|
Utime::UTIME(Timespec {
|
||||||
|
sec: mtime.sec(),
|
||||||
|
nsec: mtime.nsec(),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
Ok((atime, mtime))
|
||||||
|
} else {
|
||||||
|
Ok((Utime::UTIME(now), Utime::UTIME(now)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn timespec_valid(time: timespec_t) -> bool {
|
||||||
|
if (time.nsec() == UTIME_NOW || time.nsec() == UTIME_OMIT) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
time.sec() >= 0 && time.nsec() >= 0 && time.nsec() < 1_000_000_000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_utimes_fd(fd: FileDesc, atime: Utime, mtime: Utime, flags: i32) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"utimes_fd: fd: {:?}, atime: {:?}, mtime: {:?}, flags: {:?}",
|
||||||
|
fd, atime, mtime, flags
|
||||||
|
);
|
||||||
|
|
||||||
|
if flags != 0 {
|
||||||
|
return_errno!(EINVAL, "parameter: flags is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_ref = current!().file(fd)?;
|
||||||
|
let mut info = file_ref.metadata()?;
|
||||||
|
if let Utime::UTIME(atime) = atime {
|
||||||
|
info.atime = atime;
|
||||||
|
}
|
||||||
|
if let Utime::UTIME(mtime) = mtime {
|
||||||
|
info.mtime = mtime;
|
||||||
|
}
|
||||||
|
file_ref.set_metadata(&info)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_utimes_path(
|
||||||
|
fs_path: &FsPath,
|
||||||
|
atime: Utime,
|
||||||
|
mtime: Utime,
|
||||||
|
flags: UtimeFlags,
|
||||||
|
) -> Result<isize> {
|
||||||
|
debug!(
|
||||||
|
"utimes_path: fs_path: {:?}, atime: {:?}, mtime: {:?}, flags: {:?}",
|
||||||
|
fs_path, atime, mtime, flags
|
||||||
|
);
|
||||||
|
|
||||||
|
let inode = {
|
||||||
|
let path = fs_path.to_abs_path()?;
|
||||||
|
let current = current!();
|
||||||
|
let fs = current.fs().read().unwrap();
|
||||||
|
if flags.contains(UtimeFlags::AT_SYMLINK_NOFOLLOW) {
|
||||||
|
fs.lookup_inode_no_follow(&path)?
|
||||||
|
} else {
|
||||||
|
fs.lookup_inode(&path)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut info = inode.metadata()?;
|
||||||
|
if let Utime::UTIME(atime) = atime {
|
||||||
|
info.atime = atime;
|
||||||
|
}
|
||||||
|
if let Utime::UTIME(mtime) = mtime {
|
||||||
|
info.mtime = mtime;
|
||||||
|
}
|
||||||
|
inode.set_metadata(&info)?;
|
||||||
|
Ok(0)
|
||||||
|
}
|
@ -19,8 +19,8 @@ pub use self::event_file::{AsEvent, EventCreationFlags, EventFile};
|
|||||||
pub use self::events::{AtomicIoEvents, IoEvents, IoNotifier};
|
pub use self::events::{AtomicIoEvents, IoEvents, IoNotifier};
|
||||||
pub use self::file::{File, FileRef};
|
pub use self::file::{File, FileRef};
|
||||||
pub use self::file_ops::{
|
pub use self::file_ops::{
|
||||||
occlum_ocall_ioctl, AccessMode, BuiltinIoctlNum, CreationFlags, FallocateFlags, FileMode,
|
occlum_ocall_ioctl, utimbuf_t, AccessMode, BuiltinIoctlNum, CreationFlags, FallocateFlags,
|
||||||
IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
|
FileMode, IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
|
||||||
};
|
};
|
||||||
pub use self::file_table::{FileDesc, FileTable, FileTableEvent, FileTableNotifier};
|
pub use self::file_table::{FileDesc, FileTable, FileTableEvent, FileTableNotifier};
|
||||||
pub use self::fs_ops::Statfs;
|
pub use self::fs_ops::Statfs;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use super::event_file::EventCreationFlags;
|
use super::event_file::EventCreationFlags;
|
||||||
use super::file_ops;
|
use super::file_ops;
|
||||||
use super::file_ops::{
|
use super::file_ops::{
|
||||||
get_abs_path_by_fd, AccessibilityCheckFlags, AccessibilityCheckMode, ChownFlags, FcntlCmd,
|
get_abs_path_by_fd, get_utimes, AccessibilityCheckFlags, AccessibilityCheckMode, ChownFlags,
|
||||||
FsPath, LinkFlags, StatFlags, UnlinkFlags, AT_FDCWD,
|
FcntlCmd, FsPath, LinkFlags, StatFlags, UnlinkFlags, Utime, UtimeFlags, AT_FDCWD, UTIME_OMIT,
|
||||||
};
|
};
|
||||||
use super::fs_ops;
|
use super::fs_ops;
|
||||||
use super::fs_ops::{MountFlags, MountOptions, UmountFlags};
|
use super::fs_ops::{MountFlags, MountOptions, UmountFlags};
|
||||||
use super::time::{clockid_t, itimerspec_t, ClockID};
|
use super::time::{clockid_t, itimerspec_t, timespec_t, timeval_t, ClockID};
|
||||||
use super::timer_file::{TimerCreationFlags, TimerSetFlags};
|
use super::timer_file::{TimerCreationFlags, TimerSetFlags};
|
||||||
use super::*;
|
use super::*;
|
||||||
use config::ConfigMountFsType;
|
use config::ConfigMountFsType;
|
||||||
@ -700,3 +700,87 @@ pub fn do_flock(fd: FileDesc, operation: i32) -> Result<isize> {
|
|||||||
file_ops::do_flock(fd, flock_ops)?;
|
file_ops::do_flock(fd, flock_ops)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn do_utime(path: *const i8, times_u: *const utimbuf_t) -> Result<isize> {
|
||||||
|
let times = if !times_u.is_null() {
|
||||||
|
from_user::check_ptr(times_u)?;
|
||||||
|
let utimbuf = unsafe { *times_u };
|
||||||
|
let atime = timespec_t::from(utimbuf.atime());
|
||||||
|
atime.validate()?;
|
||||||
|
let mtime = timespec_t::from(utimbuf.mtime());
|
||||||
|
mtime.validate()?;
|
||||||
|
Some((atime, mtime))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let (atime, mtime) = file_ops::get_utimes(times)?;
|
||||||
|
self::do_utimes_wrapper(AT_FDCWD, path, atime, mtime, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_utimes(path: *const i8, times: *const timeval_t) -> Result<isize> {
|
||||||
|
self::do_futimesat(AT_FDCWD, path, times)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_futimesat(dirfd: i32, path: *const i8, times_u: *const timeval_t) -> Result<isize> {
|
||||||
|
let times = if !times_u.is_null() {
|
||||||
|
from_user::check_array(times_u, 2)?;
|
||||||
|
let atime_ptr = unsafe { times_u.offset(0) };
|
||||||
|
let atime = unsafe { *atime_ptr };
|
||||||
|
let atime = timespec_t::from(atime);
|
||||||
|
atime.validate()?;
|
||||||
|
let mtime_ptr = unsafe { times_u.offset(1) };
|
||||||
|
let mtime = unsafe { *mtime_ptr };
|
||||||
|
let mtime = timespec_t::from(mtime);
|
||||||
|
mtime.validate()?;
|
||||||
|
Some((atime, mtime))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let (atime, mtime) = file_ops::get_utimes(times)?;
|
||||||
|
self::do_utimes_wrapper(dirfd, path, atime, mtime, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_utimensat(
|
||||||
|
dirfd: i32,
|
||||||
|
path: *const i8,
|
||||||
|
times_u: *const timespec_t,
|
||||||
|
flags: i32,
|
||||||
|
) -> Result<isize> {
|
||||||
|
let times = if !times_u.is_null() {
|
||||||
|
from_user::check_array(times_u, 2)?;
|
||||||
|
let atime_ptr = unsafe { times_u.offset(0) };
|
||||||
|
let atime = unsafe { *atime_ptr };
|
||||||
|
let mtime_ptr = unsafe { times_u.offset(1) };
|
||||||
|
let mtime = unsafe { *mtime_ptr };
|
||||||
|
if atime.nsec() == UTIME_OMIT && mtime.nsec() == UTIME_OMIT {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
Some((atime, mtime))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let (atime, mtime) = file_ops::get_utimes(times)?;
|
||||||
|
self::do_utimes_wrapper(dirfd, path, atime, mtime, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_utimes_wrapper(
|
||||||
|
dirfd: i32,
|
||||||
|
path: *const i8,
|
||||||
|
atime: Utime,
|
||||||
|
mtime: Utime,
|
||||||
|
flags: i32,
|
||||||
|
) -> Result<isize> {
|
||||||
|
if path.is_null() && dirfd != AT_FDCWD {
|
||||||
|
file_ops::do_utimes_fd(dirfd as FileDesc, atime, mtime, flags)
|
||||||
|
} else {
|
||||||
|
let path = from_user::clone_cstring_safely(path)?
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
let flags = UtimeFlags::from_bits(flags).ok_or_else(|| errno!(EINVAL, "invalid flags"))?;
|
||||||
|
let fs_path = FsPath::new(&path, dirfd, false)?;
|
||||||
|
file_ops::do_utimes_path(&fs_path, atime, mtime, flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -25,13 +25,14 @@ use crate::fs::{
|
|||||||
do_access, do_chdir, do_chmod, do_chown, do_close, do_creat, do_dup, do_dup2, do_dup3,
|
do_access, do_chdir, do_chmod, do_chown, do_close, do_creat, do_dup, do_dup2, do_dup3,
|
||||||
do_eventfd, do_eventfd2, do_faccessat, do_fallocate, do_fchdir, do_fchmod, do_fchmodat,
|
do_eventfd, do_eventfd2, do_faccessat, do_fallocate, do_fchdir, do_fchmod, do_fchmodat,
|
||||||
do_fchown, do_fchownat, do_fcntl, do_fdatasync, do_flock, do_fstat, do_fstatat, do_fstatfs,
|
do_fchown, do_fchownat, do_fcntl, do_fdatasync, do_flock, do_fstat, do_fstatat, do_fstatfs,
|
||||||
do_fsync, do_ftruncate, do_getcwd, do_getdents, do_getdents64, do_ioctl, do_lchown, do_link,
|
do_fsync, do_ftruncate, do_futimesat, do_getcwd, do_getdents, do_getdents64, do_ioctl,
|
||||||
do_linkat, do_lseek, do_lstat, do_mkdir, do_mkdirat, do_mount, do_mount_rootfs, do_open,
|
do_lchown, do_link, do_linkat, do_lseek, do_lstat, do_mkdir, do_mkdirat, do_mount,
|
||||||
do_openat, do_pipe, do_pipe2, do_pread, do_pwrite, do_read, do_readlink, do_readlinkat,
|
do_mount_rootfs, do_open, do_openat, do_pipe, do_pipe2, do_pread, do_pwrite, do_read,
|
||||||
do_readv, do_rename, do_renameat, do_rmdir, do_sendfile, do_stat, do_statfs, do_symlink,
|
do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir, do_sendfile, do_stat,
|
||||||
do_symlinkat, do_sync, do_timerfd_create, do_timerfd_gettime, do_timerfd_settime, do_truncate,
|
do_statfs, do_symlink, do_symlinkat, do_sync, do_timerfd_create, do_timerfd_gettime,
|
||||||
do_umask, do_umount, do_unlink, do_unlinkat, do_write, do_writev, iovec_t, AsTimer, File,
|
do_timerfd_settime, do_truncate, do_umask, do_umount, do_unlink, do_unlinkat, do_utime,
|
||||||
FileDesc, FileRef, HostStdioFds, Stat, Statfs,
|
do_utimensat, do_utimes, do_write, do_writev, iovec_t, utimbuf_t, AsTimer, File, FileDesc,
|
||||||
|
FileRef, HostStdioFds, Stat, Statfs,
|
||||||
};
|
};
|
||||||
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
|
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
|
||||||
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t, RandFlags};
|
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t, RandFlags};
|
||||||
@ -220,7 +221,7 @@ macro_rules! process_syscall_table_with_callback {
|
|||||||
(RtSigqueueinfo = 129) => handle_unsupported(),
|
(RtSigqueueinfo = 129) => handle_unsupported(),
|
||||||
(RtSigsuspend = 130) => handle_unsupported(),
|
(RtSigsuspend = 130) => handle_unsupported(),
|
||||||
(Sigaltstack = 131) => do_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t, context: *const CpuContext),
|
(Sigaltstack = 131) => do_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t, context: *const CpuContext),
|
||||||
(Utime = 132) => handle_unsupported(),
|
(Utime = 132) => do_utime(path: *const i8, times: *const utimbuf_t),
|
||||||
(Mknod = 133) => handle_unsupported(),
|
(Mknod = 133) => handle_unsupported(),
|
||||||
(Uselib = 134) => handle_unsupported(),
|
(Uselib = 134) => handle_unsupported(),
|
||||||
(Personality = 135) => handle_unsupported(),
|
(Personality = 135) => handle_unsupported(),
|
||||||
@ -323,7 +324,7 @@ macro_rules! process_syscall_table_with_callback {
|
|||||||
(EpollWait = 232) => do_epoll_wait(epfd: c_int, events: *mut libc::epoll_event, maxevents: c_int, timeout: c_int),
|
(EpollWait = 232) => do_epoll_wait(epfd: c_int, events: *mut libc::epoll_event, maxevents: c_int, timeout: c_int),
|
||||||
(EpollCtl = 233) => do_epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *const libc::epoll_event),
|
(EpollCtl = 233) => do_epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *const libc::epoll_event),
|
||||||
(Tgkill = 234) => do_tgkill(pid: i32, tid: pid_t, sig: c_int),
|
(Tgkill = 234) => do_tgkill(pid: i32, tid: pid_t, sig: c_int),
|
||||||
(Utimes = 235) => handle_unsupported(),
|
(Utimes = 235) => do_utimes(path: *const i8, times: *const timeval_t),
|
||||||
(Vserver = 236) => handle_unsupported(),
|
(Vserver = 236) => handle_unsupported(),
|
||||||
(Mbind = 237) => handle_unsupported(),
|
(Mbind = 237) => handle_unsupported(),
|
||||||
(SetMempolicy = 238) => handle_unsupported(),
|
(SetMempolicy = 238) => handle_unsupported(),
|
||||||
@ -349,7 +350,7 @@ macro_rules! process_syscall_table_with_callback {
|
|||||||
(Mkdirat = 258) => do_mkdirat(dirfd: i32, path: *const i8, mode: u16),
|
(Mkdirat = 258) => do_mkdirat(dirfd: i32, path: *const i8, mode: u16),
|
||||||
(Mknodat = 259) => handle_unsupported(),
|
(Mknodat = 259) => handle_unsupported(),
|
||||||
(Fchownat = 260) => do_fchownat(dirfd: i32, path: *const i8, uid: u32, gid: u32, flags: i32),
|
(Fchownat = 260) => do_fchownat(dirfd: i32, path: *const i8, uid: u32, gid: u32, flags: i32),
|
||||||
(Futimesat = 261) => handle_unsupported(),
|
(Futimesat = 261) => do_futimesat(dirfd: i32, path: *const i8, times: *const timeval_t),
|
||||||
(Fstatat = 262) => do_fstatat(dirfd: i32, path: *const i8, stat_buf: *mut Stat, flags: u32),
|
(Fstatat = 262) => do_fstatat(dirfd: i32, path: *const i8, stat_buf: *mut Stat, flags: u32),
|
||||||
(Unlinkat = 263) => do_unlinkat(dirfd: i32, path: *const i8, flags: i32),
|
(Unlinkat = 263) => do_unlinkat(dirfd: i32, path: *const i8, flags: i32),
|
||||||
(Renameat = 264) => do_renameat(olddirfd: i32, oldpath: *const i8, newdirfd: i32, newpath: *const i8),
|
(Renameat = 264) => do_renameat(olddirfd: i32, oldpath: *const i8, newdirfd: i32, newpath: *const i8),
|
||||||
@ -368,7 +369,7 @@ macro_rules! process_syscall_table_with_callback {
|
|||||||
(SyncFileRange = 277) => handle_unsupported(),
|
(SyncFileRange = 277) => handle_unsupported(),
|
||||||
(Vmsplice = 278) => handle_unsupported(),
|
(Vmsplice = 278) => handle_unsupported(),
|
||||||
(MovePages = 279) => handle_unsupported(),
|
(MovePages = 279) => handle_unsupported(),
|
||||||
(Utimensat = 280) => handle_unsupported(),
|
(Utimensat = 280) => do_utimensat(dirfd: i32, path: *const i8, times: *const timespec_t, flags: i32),
|
||||||
(EpollPwait = 281) => do_epoll_pwait(epfd: c_int, events: *mut libc::epoll_event, maxevents: c_int, timeout: c_int, sigmask: *const usize),
|
(EpollPwait = 281) => do_epoll_pwait(epfd: c_int, events: *mut libc::epoll_event, maxevents: c_int, timeout: c_int, sigmask: *const usize),
|
||||||
(Signalfd = 282) => handle_unsupported(),
|
(Signalfd = 282) => handle_unsupported(),
|
||||||
(TimerfdCreate = 283) => do_timerfd_create(clockid: clockid_t, flags: i32 ),
|
(TimerfdCreate = 283) => do_timerfd_create(clockid: clockid_t, flags: i32 ),
|
||||||
|
@ -48,6 +48,14 @@ impl timeval_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sec(&self) -> time_t {
|
||||||
|
self.sec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn usec(&self) -> suseconds_t {
|
||||||
|
self.usec
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_duration(&self) -> Duration {
|
pub fn as_duration(&self) -> Duration {
|
||||||
Duration::new(self.sec as u64, (self.usec * 1_000) as u32)
|
Duration::new(self.sec as u64, (self.usec * 1_000) as u32)
|
||||||
}
|
}
|
||||||
@ -92,6 +100,21 @@ impl From<Duration> for timespec_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<timeval_t> for timespec_t {
|
||||||
|
fn from(timval: timeval_t) -> timespec_t {
|
||||||
|
timespec_t {
|
||||||
|
sec: timval.sec(),
|
||||||
|
nsec: timval.usec() * 1_000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<time_t> for timespec_t {
|
||||||
|
fn from(time: time_t) -> timespec_t {
|
||||||
|
timespec_t { sec: time, nsec: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl timespec_t {
|
impl timespec_t {
|
||||||
pub fn from_raw_ptr(ptr: *const timespec_t) -> Result<timespec_t> {
|
pub fn from_raw_ptr(ptr: *const timespec_t) -> Result<timespec_t> {
|
||||||
let ts = unsafe { *ptr };
|
let ts = unsafe { *ptr };
|
||||||
|
Loading…
Reference in New Issue
Block a user