[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