Add errno workspace crate, fix error handling in unistd workspace

crate
This commit is contained in:
Nathan Fisher 2023-02-13 00:26:13 -05:00
parent dca08c34bb
commit 05ce5422c0
8 changed files with 478 additions and 29 deletions

8
Cargo.lock generated
View File

@ -272,6 +272,10 @@ dependencies = [
"termcolor",
]
[[package]]
name = "errno"
version = "0.1.0"
[[package]]
name = "errno"
version = "0.2.8"
@ -516,7 +520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
dependencies = [
"bitflags",
"errno",
"errno 0.2.8",
"io-lifetimes",
"libc",
"linux-raw-sys",
@ -579,6 +583,7 @@ dependencies = [
"clap_mangen",
"data-encoding",
"digest",
"errno 0.1.0",
"lazy_static",
"libc",
"md-5",
@ -723,6 +728,7 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
name = "unistd"
version = "0.1.0"
dependencies = [
"errno 0.1.0",
"libc",
"sc",
]

View File

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[workspace]
members = [ "bitflags-mini", "mount", "pw", "unistd", "unix-mode" ]
members = [ "bitflags-mini", "errno", "mount", "pw", "unistd", "unix-mode" ]
[[bin]]
name = "corebox"
@ -45,9 +45,9 @@ walkdir = "2.3"
package = "bitflags-mini"
path = "bitflags-mini"
[dependencies.unistd]
package = "unistd"
path = "unistd"
[dependencies.errno]
package = "errno"
path = "errno"
[dependencies.mode]
package = "unix-mode"
@ -56,6 +56,10 @@ path = "unix-mode"
[dependencies.mount]
path = "mount"
[dependencies.unistd]
package = "unistd"
path = "unistd"
[dependencies.pw]
path = "pw"

8
errno/Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "errno"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

425
errno/src/lib.rs Normal file
View File

@ -0,0 +1,425 @@
use core::fmt;
use std::{error, ffi::c_long};
#[derive(Debug)]
#[repr(i64)]
pub enum Errno {
EPERM = 1,
ENOENT = 2,
ESRCH = 3,
EINTR = 4,
EIO = 5,
ENXIO = 6,
E2BIG = 7,
ENOEXEC = 8,
EBADF = 9,
ECHILD = 10,
EAGAIN = 11,
ENOMEM = 12,
EACCES = 13,
EFAULT = 14,
ENOTBLK = 15,
EBUSY = 16,
EEXIST = 17,
EXDEV = 18,
ENODEV = 19,
ENOTDIR = 20,
EISDIR = 21,
EINVAL = 22,
ENFILE = 23,
EMFILE = 24,
ENOTTY = 25,
ETXTBSY = 26,
EFBIG = 27,
ENOSPC = 28,
ESPIPE = 29,
EROFS = 30,
EMLINK = 31,
EPIPE = 32,
EDOM = 33,
ERANGE = 34,
EDEADLOCK = 35,
ENAMETOOLONG = 36,
ENOLCK = 37,
ENOSYS = 38,
ENOTEMPTY = 39,
ELOOP = 40,
ENOMSG = 42,
EIDRM = 43,
ECHRNG = 44,
EL2NSYNC = 45,
EL3HLT = 46,
EL3RST = 47,
ELNRNG = 48,
EUNATCH = 49,
ENOCSI = 50,
EL2HLT = 51,
EBADE = 52,
EBADR = 53,
EXFULL = 54,
ENOANO = 55,
EBADRQC = 56,
EBADSLT = 57,
EBFONT = 59,
ENOSTR = 60,
ENODATA = 61,
ETIME = 62,
ENOSR = 63,
ENONET = 64,
ENOPKG = 65,
EREMOTE = 66,
ENOLINK = 67,
EADV = 68,
ESRMNT = 69,
ECOMM = 70,
EPROTO = 71,
EMULTIHOP = 72,
EDOTDOT = 73,
EBADMSG = 74,
EOVERFLOW = 75,
ENOTUNIQ = 76,
EBADFD = 77,
EREMCHG = 78,
ELIBACC = 79,
ELIBBAD = 80,
ELIBSCN = 81,
ELIBMAX = 82,
ELIBEXEC = 83,
EILSEQ = 84,
ERESTART = 85,
ESTRPIPE = 86,
EUSERS = 87,
ENOTSOCK = 88,
EDESTADDRREQ = 89,
EMSGSIZE = 90,
EPROTOTYPE = 91,
ENOPROTOOPT = 92,
EPROTONOSUPPORT = 93,
ESOCKTNOSUPPORT = 94,
EOPNOTSUPP = 95,
EPFNOSUPPORT = 96,
EAFNOSUPPORT = 97,
EADDRINUSE = 98,
EADDRNOTAVAIL = 99,
ENETDOWN = 100,
ENETUNREACH = 101,
ENETRESET = 102,
ECONNABORTED = 103,
ECONNRESET = 104,
ENOBUFS = 105,
EISCONN = 106,
ENOTCONN = 107,
ESHUTDOWN = 108,
ETOOMANYREFS = 109,
ETIMEDOUT = 110,
ECONNREFUSED = 111,
EHOSTDOWN = 112,
EHOSTUNREACH = 113,
EALREADY = 114,
EINPROGRESS = 115,
ESTALE = 116,
EUCLEAN = 117,
ENOTNAM = 118,
ENAVAIL = 119,
EISNAM = 120,
EREMOTEIO = 121,
EDQUOT = 122,
ENOMEDIUM = 123,
EMEDIUMTYPE = 124,
ECANCELED = 125,
ENOKEY = 126,
EKEYEXPIRED = 127,
EKEYREVOKED = 128,
EKEYREJECTED = 129,
EOWNERDEAD = 130,
ENOTRECOVERABLE = 131,
ERFKILL = 132,
EHWPOISON = 133,
Unknown(i64),
}
impl fmt::Display for Errno {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::EPERM => write!(f, "Operation not permitted"),
Self::ENOENT => write!(f, "No such file or directory"),
Self::ESRCH => write!(f, "No such process"),
Self::EINTR => write!(f, "Interrupted system call"),
Self::EIO => write!(f, "Input/output error"),
Self::ENXIO => write!(f, "No such device or address"),
Self::E2BIG => write!(f, "Argument list too long"),
Self::ENOEXEC => write!(f, "Exec format error"),
Self::EBADF => write!(f, "Bad file descriptor"),
Self::ECHILD => write!(f, "No child processes"),
Self::EAGAIN => write!(f, "Resource temporarily unavailable"),
Self::ENOMEM => write!(f, "Cannot allocate memory"),
Self::EACCES => write!(f, "Permission denied"),
Self::EFAULT => write!(f, "Bad address"),
Self::ENOTBLK => write!(f, "Block device required"),
Self::EBUSY => write!(f, "Device or resource busy"),
Self::EEXIST => write!(f, "File exists"),
Self::EXDEV => write!(f, "Invalid cross-device link"),
Self::ENODEV => write!(f, "No such device"),
Self::ENOTDIR => write!(f, "Not a directory"),
Self::EISDIR => write!(f, "Is a directory"),
Self::EINVAL => write!(f, "Invalid argument"),
Self::ENFILE => write!(f, "Too many open files in system"),
Self::EMFILE => write!(f, "Too many open files"),
Self::ENOTTY => write!(f, "Inappropriate ioctl for device"),
Self::ETXTBSY => write!(f, "Text file busy"),
Self::EFBIG => write!(f, "File too large"),
Self::ENOSPC => write!(f, "No space left on device"),
Self::ESPIPE => write!(f, "Illegal seek"),
Self::EROFS => write!(f, "Read-only file system"),
Self::EMLINK => write!(f, "Too many links"),
Self::EPIPE => write!(f, "Broken pipe"),
Self::EDOM => write!(f, "Numerical argument out of domain"),
Self::ERANGE => write!(f, "Numerical result out of range"),
Self::ENAMETOOLONG => write!(f, "File name too long"),
Self::ENOLCK => write!(f, "No locks available"),
Self::ENOSYS => write!(f, "Function not implemented"),
Self::ENOTEMPTY => write!(f, "Directory not empty"),
Self::ELOOP => write!(f, "Too many levels of symbolic links"),
Self::ENOMSG => write!(f, "No message of desired type"),
Self::EIDRM => write!(f, "Identifier removed"),
Self::ECHRNG => write!(f, "Channel number out of range"),
Self::EL2NSYNC => write!(f, "Level 2 not synchronized"),
Self::EL3HLT => write!(f, "Level 3 halted"),
Self::EL3RST => write!(f, "Level 3 reset"),
Self::ELNRNG => write!(f, "Link number out of range"),
Self::EUNATCH => write!(f, "Protocol driver not attached"),
Self::ENOCSI => write!(f, "No CSI structure available"),
Self::EL2HLT => write!(f, "Level 2 halted"),
Self::EBADE => write!(f, "Invalid exchange"),
Self::EBADR => write!(f, "Invalid request descriptor"),
Self::EXFULL => write!(f, "Exchange full"),
Self::ENOANO => write!(f, "No anode"),
Self::EBADRQC => write!(f, "Invalid request code"),
Self::EBADSLT => write!(f, "Invalid slot"),
Self::EDEADLOCK => write!(f, "Resource deadlock avoided"),
Self::EBFONT => write!(f, "Bad font file format"),
Self::ENOSTR => write!(f, "Device not a stream"),
Self::ENODATA => write!(f, "No data available"),
Self::ETIME => write!(f, "Timer expired"),
Self::ENOSR => write!(f, "Out of streams resources"),
Self::ENONET => write!(f, "Machine is not on the network"),
Self::ENOPKG => write!(f, "Package not installed"),
Self::EREMOTE => write!(f, "Object is remote"),
Self::ENOLINK => write!(f, "Link has been severed"),
Self::EADV => write!(f, "Advertise error"),
Self::ESRMNT => write!(f, "Srmount error"),
Self::ECOMM => write!(f, "Communication error on send"),
Self::EPROTO => write!(f, "Protocol error"),
Self::EMULTIHOP => write!(f, "Multihop attempted"),
Self::EDOTDOT => write!(f, "RFS specific error"),
Self::EBADMSG => write!(f, "Bad message"),
Self::EOVERFLOW => write!(f, "Value too large for defined data type"),
Self::ENOTUNIQ => write!(f, "Name not unique on network"),
Self::EBADFD => write!(f, "File descriptor in bad state"),
Self::EREMCHG => write!(f, "Remote address changed"),
Self::ELIBACC => write!(f, "Can not access a needed shared library"),
Self::ELIBBAD => write!(f, "Accessing a corrupted shared library"),
Self::ELIBSCN => write!(f, ".lib section in a.out corrupted"),
Self::ELIBMAX => write!(f, "Attempting to link in too many shared libraries"),
Self::ELIBEXEC => write!(f, "Cannot exec a shared library directly"),
Self::EILSEQ => write!(f, "Invalid or incomplete multibyte or wide character"),
Self::ERESTART => write!(f, "Interrupted system call should be restarted"),
Self::ESTRPIPE => write!(f, "Streams pipe error"),
Self::EUSERS => write!(f, "Too many users"),
Self::ENOTSOCK => write!(f, "Socket operation on non-socket"),
Self::EDESTADDRREQ => write!(f, "Destination address required"),
Self::EMSGSIZE => write!(f, "Message too long"),
Self::EPROTOTYPE => write!(f, "Protocol wrong type for socket"),
Self::ENOPROTOOPT => write!(f, "Protocol not available"),
Self::EPROTONOSUPPORT => write!(f, "Protocol not supported"),
Self::ESOCKTNOSUPPORT => write!(f, "Socket type not supported"),
Self::EOPNOTSUPP => write!(f, "Operation not supported"),
Self::EPFNOSUPPORT => write!(f, "Protocol family not supported"),
Self::EAFNOSUPPORT => write!(f, "Address family not supported by protocol"),
Self::EADDRINUSE => write!(f, "Address already in use"),
Self::EADDRNOTAVAIL => write!(f, "Cannot assign requested address"),
Self::ENETDOWN => write!(f, "Network is down"),
Self::ENETUNREACH => write!(f, "Network is unreachable"),
Self::ENETRESET => write!(f, "Network dropped connection on reset"),
Self::ECONNABORTED => write!(f, "Software caused connection abort"),
Self::ECONNRESET => write!(f, "Connection reset by peer"),
Self::ENOBUFS => write!(f, "No buffer space available"),
Self::EISCONN => write!(f, "Transport endpoint is already connected"),
Self::ENOTCONN => write!(f, "Transport endpoint is not connected"),
Self::ESHUTDOWN => write!(f, "Cannot send after transport endpoint shutdown"),
Self::ETOOMANYREFS => write!(f, "Too many references: cannot splice"),
Self::ETIMEDOUT => write!(f, "Connection timed out"),
Self::ECONNREFUSED => write!(f, "Connection refused"),
Self::EHOSTDOWN => write!(f, "Host is down"),
Self::EHOSTUNREACH => write!(f, "No route to host"),
Self::EALREADY => write!(f, "Operation already in progress"),
Self::EINPROGRESS => write!(f, "Operation now in progress"),
Self::ESTALE => write!(f, "Stale file handle"),
Self::EUCLEAN => write!(f, "Structure needs cleaning"),
Self::ENOTNAM => write!(f, "Not a XENIX named type file"),
Self::ENAVAIL => write!(f, "No XENIX semaphores available"),
Self::EISNAM => write!(f, "Is a named type file"),
Self::EREMOTEIO => write!(f, "Remote I/O error"),
Self::EDQUOT => write!(f, "Disk quota exceeded"),
Self::ENOMEDIUM => write!(f, "No medium found"),
Self::EMEDIUMTYPE => write!(f, "Wrong medium type"),
Self::ECANCELED => write!(f, "Operation canceled"),
Self::ENOKEY => write!(f, "Required key not available"),
Self::EKEYEXPIRED => write!(f, "Key has expired"),
Self::EKEYREVOKED => write!(f, "Key has been revoked"),
Self::EKEYREJECTED => write!(f, "Key was rejected by service"),
Self::EOWNERDEAD => write!(f, "Owner died"),
Self::ENOTRECOVERABLE => write!(f, "State not recoverable"),
Self::ERFKILL => write!(f, "Operation not possible due to RF-kill"),
Self::EHWPOISON => write!(f, "Memory page has hardware error"),
Self::Unknown(n) => write!(f, "Unknown error {n}"),
}
}
}
impl error::Error for Errno {}
impl From<usize> for Errno {
fn from(value: usize) -> Self {
(-(value as c_long)).into()
}
}
impl From<c_long> for Errno {
fn from(value: c_long) -> Self {
match value {
1 => Self::EPERM,
2 => Self::ENOENT,
3 => Self::ESRCH,
4 => Self::EINTR,
5 => Self::EIO,
6 => Self::ENXIO,
7 => Self::E2BIG,
8 => Self::ENOEXEC,
9 => Self::EBADF,
10 => Self::ECHILD,
11 => Self::EAGAIN,
12 => Self::ENOMEM,
13 => Self::EACCES,
14 => Self::EFAULT,
15 => Self::ENOTBLK,
16 => Self::EBUSY,
17 => Self::EEXIST,
18 => Self::EXDEV,
19 => Self::ENODEV,
20 => Self::ENOTDIR,
21 => Self::EISDIR,
22 => Self::EINVAL,
23 => Self::ENFILE,
24 => Self::EMFILE,
25 => Self::ENOTTY,
26 => Self::ETXTBSY,
27 => Self::EFBIG,
28 => Self::ENOSPC,
29 => Self::ESPIPE,
30 => Self::EROFS,
31 => Self::EMLINK,
32 => Self::EPIPE,
33 => Self::EDOM,
34 => Self::ERANGE,
35 => Self::EDEADLOCK,
36 => Self::ENAMETOOLONG,
37 => Self::ENOLCK,
38 => Self::ENOSYS,
39 => Self::ENOTEMPTY,
40 => Self::ELOOP,
42 => Self::ENOMSG,
43 => Self::EIDRM,
44 => Self::ECHRNG,
45 => Self::EL2NSYNC,
46 => Self::EL3HLT,
47 => Self::EL3RST,
48 => Self::ELNRNG,
49 => Self::EUNATCH,
50 => Self::ENOCSI,
51 => Self::EL2HLT,
52 => Self::EBADE,
53 => Self::EBADR,
54 => Self::EXFULL,
55 => Self::ENOANO,
56 => Self::EBADRQC,
57 => Self::EBADSLT,
59 => Self::EBFONT,
60 => Self::ENOSTR,
61 => Self::ENODATA,
62 => Self::ETIME,
63 => Self::ENOSR,
64 => Self::ENONET,
65 => Self::ENOPKG,
66 => Self::EREMOTE,
67 => Self::ENOLINK,
68 => Self::EADV,
69 => Self::ESRMNT,
70 => Self::ECOMM,
71 => Self::EPROTO,
72 => Self::EMULTIHOP,
73 => Self::EDOTDOT,
74 => Self::EBADMSG,
75 => Self::EOVERFLOW,
76 => Self::ENOTUNIQ,
77 => Self::EBADFD,
78 => Self::EREMCHG,
79 => Self::ELIBACC,
80 => Self::ELIBBAD,
81 => Self::ELIBSCN,
82 => Self::ELIBMAX,
83 => Self::ELIBEXEC,
84 => Self::EILSEQ,
85 => Self::ERESTART,
86 => Self::ESTRPIPE,
87 => Self::EUSERS,
88 => Self::ENOTSOCK,
89 => Self::EDESTADDRREQ,
90 => Self::EMSGSIZE,
91 => Self::EPROTOTYPE,
92 => Self::ENOPROTOOPT,
93 => Self::EPROTONOSUPPORT,
94 => Self::ESOCKTNOSUPPORT,
95 => Self::EOPNOTSUPP,
96 => Self::EPFNOSUPPORT,
97 => Self::EAFNOSUPPORT,
98 => Self::EADDRINUSE,
99 => Self::EADDRNOTAVAIL,
100 => Self::ENETDOWN,
101 => Self::ENETUNREACH,
102 => Self::ENETRESET,
103 => Self::ECONNABORTED,
104 => Self::ECONNRESET,
105 => Self::ENOBUFS,
106 => Self::EISCONN,
107 => Self::ENOTCONN,
108 => Self::ESHUTDOWN,
109 => Self::ETOOMANYREFS,
110 => Self::ETIMEDOUT,
111 => Self::ECONNREFUSED,
112 => Self::EHOSTDOWN,
113 => Self::EHOSTUNREACH,
114 => Self::EALREADY,
115 => Self::EINPROGRESS,
116 => Self::ESTALE,
117 => Self::EUCLEAN,
118 => Self::ENOTNAM,
119 => Self::ENAVAIL,
120 => Self::EISNAM,
121 => Self::EREMOTEIO,
122 => Self::EDQUOT,
123 => Self::ENOMEDIUM,
124 => Self::EMEDIUMTYPE,
125 => Self::ECANCELED,
126 => Self::ENOKEY,
127 => Self::EKEYEXPIRED,
128 => Self::EKEYREVOKED,
129 => Self::EKEYREJECTED,
130 => Self::EOWNERDEAD,
131 => Self::ENOTRECOVERABLE,
132 => Self::ERFKILL,
133 => Self::EHWPOISON,
n => Self::Unknown(n),
}
}
}

View File

@ -3,7 +3,7 @@ use crate::hash::{self, HashType};
use clap::Command;
use sha2::{Digest, Sha224};
use shitbox::args;
use std::{io, process};
use std::io;
#[derive(Debug, Default)]
pub struct Sha224sum;

View File

@ -83,7 +83,7 @@ pub fn get_grpname<'a>() -> Result<&'a str, std::str::Utf8Error> {
pub fn get_gid_for_groupname(groupname: &str) -> Option<u32> {
let Ok(grp) = CString::new(groupname.as_bytes()) else { return None };
unsafe { Some((*libc::getgrnam(grp.as_ptr())).gr_gid as u32) }
unsafe { Some((*libc::getgrnam(grp.as_ptr())).gr_gid) }
}
pub fn get_groupname_for_gid<'a>(gid: u32) -> Result<&'a str, std::str::Utf8Error> {

View File

@ -8,3 +8,7 @@ edition = "2021"
[dependencies]
libc = { workspace = true }
sc = { workspace = true }
[dependencies.errno]
package = "errno"
path = "../errno"

View File

@ -1,6 +1,7 @@
use errno::Errno;
use libc::utsname;
use sc::syscall;
use std::{ffi::CString, fs::File, io, os::fd::AsRawFd, u8};
use std::{error::Error, ffi::CString, fs::File, os::fd::AsRawFd, u8};
#[inline(always)]
fn new_utsname() -> utsname {
@ -15,11 +16,12 @@ fn new_utsname() -> utsname {
}
#[inline(always)]
pub fn gethostname() -> io::Result<String> {
pub fn gethostname() -> Result<String, Box<dyn Error>> {
let mut uts = new_utsname();
unsafe {
if syscall!(UNAME, &mut uts as *mut utsname) != 0 {
return Err(io::Error::last_os_error());
let ret = syscall!(UNAME, &mut uts as *mut utsname);
if ret != 0 {
return Err(Errno::from(ret).into());
}
}
let name = uts
@ -28,21 +30,21 @@ pub fn gethostname() -> io::Result<String> {
.map(|x| *x as u8)
.take_while(|x| *x != 0)
.collect();
String::from_utf8(name).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
String::from_utf8(name).map_err(|e| e.into())
}
#[inline(always)]
pub fn sethostname(name: &str) -> io::Result<()> {
pub fn sethostname(name: &str) -> Result<(), Errno> {
let ret = unsafe { syscall!(SETHOSTNAME, name.as_ptr(), name.len()) };
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error().into())
Err(ret.into())
}
}
#[inline(always)]
pub fn link(source: &str, dest: &str) -> io::Result<()> {
pub fn link(source: &str, dest: &str) -> Result<(), Box<dyn Error>> {
let ret = unsafe {
syscall!(
LINKAT,
@ -56,22 +58,22 @@ pub fn link(source: &str, dest: &str) -> io::Result<()> {
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
Err(Errno::from(ret).into())
}
}
#[inline(always)]
pub fn unlink(name: &str) -> io::Result<()> {
pub fn unlink(name: &str) -> Result<(), Box<dyn Error>> {
let ret = unsafe { syscall!(UNLINKAT, libc::AT_FDCWD, CString::new(name)?.as_ptr(), 0) };
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error().into())
Err(Errno::from(ret).into())
}
}
#[inline(always)]
pub fn readlink(name: &str) -> io::Result<String> {
pub fn readlink(name: &str) -> Result<String, Box<dyn Error>> {
let mut buf = Vec::<i8>::with_capacity(1024);
let ret = unsafe {
syscall!(
@ -88,39 +90,39 @@ pub fn readlink(name: &str) -> io::Result<String> {
.map(|x| *x as u8)
.take_while(|x| *x != 0)
.collect();
String::from_utf8(path).map_err(|e| io::Error::new(io::ErrorKind::Other, e))
String::from_utf8(path).map_err(|e| e.into())
} else {
Err(io::Error::last_os_error())
Err(Errno::from(ret).into())
}
}
#[inline(always)]
pub fn fdatasync(fd: &File) -> io::Result<()> {
pub fn fdatasync(fd: &File) -> Result<(), Errno> {
let ret = unsafe { syscall!(FDATASYNC, fd.as_raw_fd()) };
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
Err(ret.into())
}
}
#[inline(always)]
pub fn syncfs(fd: &File) -> io::Result<()> {
pub fn syncfs(fd: &File) -> Result<(), Errno> {
let ret = unsafe { syscall!(SYNCFS, fd.as_raw_fd()) };
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
Err(ret.into())
}
}
#[inline(always)]
pub fn fsync(fd: &File) -> io::Result<()> {
pub fn fsync(fd: &File) -> Result<(), Errno> {
let ret = unsafe { syscall!(FSYNC, fd.as_raw_fd()) };
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
Err(ret.into())
}
}
@ -130,7 +132,7 @@ pub fn sync() {
}
#[inline(always)]
pub fn symlink(source: &str, dest: &str) -> io::Result<()> {
pub fn symlink(source: &str, dest: &str) -> Result<(), Box<dyn Error>> {
let ret = unsafe {
syscall!(
SYMLINKAT,
@ -142,6 +144,6 @@ pub fn symlink(source: &str, dest: &str) -> io::Result<()> {
if ret == 0 {
Ok(())
} else {
Err(io::Error::last_os_error())
Err(Errno::from(ret).into())
}
}