Skip to main content

linux_api/
errno.rs

1use crate::bindings;
2
3#[derive(Copy, Clone, PartialEq, Eq)]
4// Defined in libc as an `int`, but u16 is sufficient
5// to represent all values, and is what is used in `linux_errno`.
6//
7// We want to allow unknown values, but only up to Errno::MAX, making
8// it difficult to use an `enum` here. e.g. if we used `num_enum` with a `catch_all` `Unknown`
9// variant, we wouldn't be able to prevent construction of `Errno::Unknown(Errno::MAX.into() + 1)`.
10pub struct Errno(u16);
11
12impl TryFrom<u16> for Errno {
13    type Error = ();
14
15    fn try_from(val: u16) -> Result<Self, Self::Error> {
16        Self::from_u16(val).ok_or(())
17    }
18}
19
20impl TryFrom<u32> for Errno {
21    type Error = ();
22
23    fn try_from(val: u32) -> Result<Self, Self::Error> {
24        u16::try_from(val).ok().and_then(Self::from_u16).ok_or(())
25    }
26}
27
28impl TryFrom<u64> for Errno {
29    type Error = ();
30
31    fn try_from(val: u64) -> Result<Self, Self::Error> {
32        u16::try_from(val).ok().and_then(Self::from_u16).ok_or(())
33    }
34}
35
36impl TryFrom<i16> for Errno {
37    type Error = ();
38
39    fn try_from(val: i16) -> Result<Self, Self::Error> {
40        u16::try_from(val).ok().and_then(Self::from_u16).ok_or(())
41    }
42}
43
44impl TryFrom<i32> for Errno {
45    type Error = ();
46
47    fn try_from(val: i32) -> Result<Self, Self::Error> {
48        u16::try_from(val).ok().and_then(Self::from_u16).ok_or(())
49    }
50}
51
52impl TryFrom<i64> for Errno {
53    type Error = ();
54
55    fn try_from(val: i64) -> Result<Self, Self::Error> {
56        u16::try_from(val).ok().and_then(Self::from_u16).ok_or(())
57    }
58}
59
60impl From<Errno> for u16 {
61    #[inline]
62    fn from(val: Errno) -> u16 {
63        val.0
64    }
65}
66
67impl From<Errno> for u32 {
68    #[inline]
69    fn from(val: Errno) -> u32 {
70        val.0.into()
71    }
72}
73
74impl From<Errno> for u64 {
75    #[inline]
76    fn from(val: Errno) -> u64 {
77        val.0.into()
78    }
79}
80
81impl From<Errno> for i32 {
82    #[inline]
83    fn from(val: Errno) -> i32 {
84        val.0.into()
85    }
86}
87
88impl From<Errno> for i64 {
89    #[inline]
90    fn from(val: Errno) -> i64 {
91        val.0.into()
92    }
93}
94
95const fn errno_to_str(e: Errno) -> Option<&'static str> {
96    match e {
97        Errno::ENODEV => Some("ENODEV"),
98        Errno::EINVAL => Some("EINVAL"),
99        Errno::EDEADLK => Some("EDEADLK"),
100        Errno::ENAMETOOLONG => Some("ENAMETOOLONG"),
101        Errno::ENOLCK => Some("ENOLCK"),
102        Errno::ENOSYS => Some("ENOSYS"),
103        Errno::ENOTEMPTY => Some("ENOTEMPTY"),
104        Errno::ELOOP => Some("ELOOP"),
105        Errno::EWOULDBLOCK => Some("EWOULDBLOCK"),
106        Errno::ENOMSG => Some("ENOMSG"),
107        Errno::EIDRM => Some("EIDRM"),
108        Errno::ECHRNG => Some("ECHRNG"),
109        Errno::EL2NSYNC => Some("EL2NSYNC"),
110        Errno::EL3HLT => Some("EL3HLT"),
111        Errno::EL3RST => Some("EL3RST"),
112        Errno::ELNRNG => Some("ELNRNG"),
113        Errno::EUNATCH => Some("EUNATCH"),
114        Errno::ENOCSI => Some("ENOCSI"),
115        Errno::EL2HLT => Some("EL2HLT"),
116        Errno::EBADE => Some("EBADE"),
117        Errno::EBADR => Some("EBADR"),
118        Errno::EXFULL => Some("EXFULL"),
119        Errno::ENOANO => Some("ENOANO"),
120        Errno::EBADRQC => Some("EBADRQC"),
121        Errno::EBADSLT => Some("EBADSLT"),
122        Errno::EBFONT => Some("EBFONT"),
123        Errno::ENOSTR => Some("ENOSTR"),
124        Errno::ENODATA => Some("ENODATA"),
125        Errno::ETIME => Some("ETIME"),
126        Errno::ENOSR => Some("ENOSR"),
127        Errno::ENONET => Some("ENONET"),
128        Errno::ENOPKG => Some("ENOPKG"),
129        Errno::EREMOTE => Some("EREMOTE"),
130        Errno::ENOLINK => Some("ENOLINK"),
131        Errno::EADV => Some("EADV"),
132        Errno::ESRMNT => Some("ESRMNT"),
133        Errno::ECOMM => Some("ECOMM"),
134        Errno::EPROTO => Some("EPROTO"),
135        Errno::EMULTIHOP => Some("EMULTIHOP"),
136        Errno::EDOTDOT => Some("EDOTDOT"),
137        Errno::EBADMSG => Some("EBADMSG"),
138        // Currently aliased to EBADMSG
139        #[expect(unreachable_patterns)]
140        Errno::EFSBADCRC => Some("EFSBADCRC"),
141        Errno::EOVERFLOW => Some("EOVERFLOW"),
142        Errno::ENOTUNIQ => Some("ENOTUNIQ"),
143        Errno::EBADFD => Some("EBADFD"),
144        Errno::EREMCHG => Some("EREMCHG"),
145        Errno::ELIBACC => Some("ELIBACC"),
146        Errno::ELIBBAD => Some("ELIBBAD"),
147        Errno::ELIBSCN => Some("ELIBSCN"),
148        Errno::ELIBMAX => Some("ELIBMAX"),
149        Errno::ELIBEXEC => Some("ELIBEXEC"),
150        Errno::EILSEQ => Some("EILSEQ"),
151        Errno::ERESTART => Some("ERESTART"),
152        Errno::ESTRPIPE => Some("ESTRPIPE"),
153        Errno::EUSERS => Some("EUSERS"),
154        Errno::ENOTSOCK => Some("ENOTSOCK"),
155        Errno::EDESTADDRREQ => Some("EDESTADDRREQ"),
156        Errno::EMSGSIZE => Some("EMSGSIZE"),
157        Errno::EPROTOTYPE => Some("EPROTOTYPE"),
158        Errno::ENOPROTOOPT => Some("ENOPROTOOPT"),
159        Errno::EPROTONOSUPPORT => Some("EPROTONOSUPPORT"),
160        Errno::ESOCKTNOSUPPORT => Some("ESOCKTNOSUPPORT"),
161        Errno::EOPNOTSUPP => Some("EOPNOTSUPP"),
162        Errno::EPFNOSUPPORT => Some("EPFNOSUPPORT"),
163        Errno::EAFNOSUPPORT => Some("EAFNOSUPPORT"),
164        Errno::EADDRINUSE => Some("EADDRINUSE"),
165        Errno::EADDRNOTAVAIL => Some("EADDRNOTAVAIL"),
166        Errno::ENETDOWN => Some("ENETDOWN"),
167        Errno::ENETUNREACH => Some("ENETUNREACH"),
168        Errno::ENETRESET => Some("ENETRESET"),
169        Errno::ECONNABORTED => Some("ECONNABORTED"),
170        Errno::ECONNRESET => Some("ECONNRESET"),
171        Errno::ENOBUFS => Some("ENOBUFS"),
172        Errno::EISCONN => Some("EISCONN"),
173        Errno::ENOTCONN => Some("ENOTCONN"),
174        Errno::ESHUTDOWN => Some("ESHUTDOWN"),
175        Errno::ETOOMANYREFS => Some("ETOOMANYREFS"),
176        Errno::ETIMEDOUT => Some("ETIMEDOUT"),
177        Errno::ECONNREFUSED => Some("ECONNREFUSED"),
178        Errno::EHOSTDOWN => Some("EHOSTDOWN"),
179        Errno::EHOSTUNREACH => Some("EHOSTUNREACH"),
180        Errno::EALREADY => Some("EALREADY"),
181        Errno::EINPROGRESS => Some("EINPROGRESS"),
182        Errno::ESTALE => Some("ESTALE"),
183        Errno::EUCLEAN => Some("EUCLEAN"),
184        // Currently aliased to EUCLEAN
185        #[expect(unreachable_patterns)]
186        Errno::EFSCORRUPTED => Some("EFSCORRUPTED"),
187        Errno::ENOTNAM => Some("ENOTNAM"),
188        Errno::ENAVAIL => Some("ENAVAIL"),
189        Errno::EISNAM => Some("EISNAM"),
190        Errno::EREMOTEIO => Some("EREMOTEIO"),
191        Errno::EDQUOT => Some("EDQUOT"),
192        Errno::ENOMEDIUM => Some("ENOMEDIUM"),
193        Errno::EMEDIUMTYPE => Some("EMEDIUMTYPE"),
194        Errno::ECANCELED => Some("ECANCELED"),
195        Errno::ENOKEY => Some("ENOKEY"),
196        Errno::EKEYEXPIRED => Some("EKEYEXPIRED"),
197        Errno::EKEYREVOKED => Some("EKEYREVOKED"),
198        Errno::EKEYREJECTED => Some("EKEYREJECTED"),
199        Errno::EOWNERDEAD => Some("EOWNERDEAD"),
200        Errno::ENOTRECOVERABLE => Some("ENOTRECOVERABLE"),
201        Errno::ERFKILL => Some("ERFKILL"),
202        Errno::EHWPOISON => Some("EHWPOISON"),
203        Errno::EINTR => Some("EINTR"),
204        Errno::ENFILE => Some("ENFILE"),
205        Errno::EPIPE => Some("EPIPE"),
206        Errno::ESPIPE => Some("ESPIPE"),
207        Errno::EBADF => Some("EBADF"),
208        Errno::EPERM => Some("EPERM"),
209        Errno::EFAULT => Some("EFAULT"),
210        Errno::ESRCH => Some("ESRCH"),
211        Errno::ENOENT => Some("ENOENT"),
212        Errno::ENOTTY => Some("ENOTTY"),
213        Errno::EEXIST => Some("EEXIST"),
214        Errno::ECHILD => Some("ECHILD"),
215        Errno::EACCES => Some("EACCES"),
216        Errno::ENOEXEC => Some("ENOEXEC"),
217        Errno::ENOTDIR => Some("ENOTDIR"),
218        _ => None,
219    }
220}
221
222impl core::fmt::Debug for Errno {
223    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
224        match errno_to_str(*self) {
225            Some(s) => {
226                formatter.write_str("Errno::")?;
227                formatter.write_str(s)
228            }
229            None => write!(formatter, "Errno::<{}>", u16::from(*self)),
230        }
231    }
232}
233
234impl core::fmt::Display for Errno {
235    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
236        match errno_to_str(*self) {
237            Some(s) => formatter.write_str(s),
238            None => write!(formatter, "(unknown errno {})", u16::from(*self)),
239        }
240    }
241}
242
243impl Errno {
244    pub const ENODEV: Self = Self::from_u32_const(bindings::LINUX_ENODEV);
245    pub const EINVAL: Self = Self::from_u32_const(bindings::LINUX_EINVAL);
246    pub const EDEADLK: Self = Self::from_u32_const(bindings::LINUX_EDEADLK);
247    pub const ENAMETOOLONG: Self = Self::from_u32_const(bindings::LINUX_ENAMETOOLONG);
248    pub const ENOLCK: Self = Self::from_u32_const(bindings::LINUX_ENOLCK);
249    pub const ENOSYS: Self = Self::from_u32_const(bindings::LINUX_ENOSYS);
250    pub const ENOTEMPTY: Self = Self::from_u32_const(bindings::LINUX_ENOTEMPTY);
251    pub const ELOOP: Self = Self::from_u32_const(bindings::LINUX_ELOOP);
252    pub const EWOULDBLOCK: Self = Self::from_u32_const(bindings::LINUX_EWOULDBLOCK);
253    pub const ENOMSG: Self = Self::from_u32_const(bindings::LINUX_ENOMSG);
254    pub const EIDRM: Self = Self::from_u32_const(bindings::LINUX_EIDRM);
255    pub const ECHRNG: Self = Self::from_u32_const(bindings::LINUX_ECHRNG);
256    pub const EL2NSYNC: Self = Self::from_u32_const(bindings::LINUX_EL2NSYNC);
257    pub const EL3HLT: Self = Self::from_u32_const(bindings::LINUX_EL3HLT);
258    pub const EL3RST: Self = Self::from_u32_const(bindings::LINUX_EL3RST);
259    pub const ELNRNG: Self = Self::from_u32_const(bindings::LINUX_ELNRNG);
260    pub const EUNATCH: Self = Self::from_u32_const(bindings::LINUX_EUNATCH);
261    pub const ENOCSI: Self = Self::from_u32_const(bindings::LINUX_ENOCSI);
262    pub const EL2HLT: Self = Self::from_u32_const(bindings::LINUX_EL2HLT);
263    pub const EBADE: Self = Self::from_u32_const(bindings::LINUX_EBADE);
264    pub const EBADR: Self = Self::from_u32_const(bindings::LINUX_EBADR);
265    pub const EXFULL: Self = Self::from_u32_const(bindings::LINUX_EXFULL);
266    pub const ENOANO: Self = Self::from_u32_const(bindings::LINUX_ENOANO);
267    pub const EBADRQC: Self = Self::from_u32_const(bindings::LINUX_EBADRQC);
268    pub const EBADSLT: Self = Self::from_u32_const(bindings::LINUX_EBADSLT);
269    pub const EBFONT: Self = Self::from_u32_const(bindings::LINUX_EBFONT);
270    pub const ENOSTR: Self = Self::from_u32_const(bindings::LINUX_ENOSTR);
271    pub const ENODATA: Self = Self::from_u32_const(bindings::LINUX_ENODATA);
272    pub const ETIME: Self = Self::from_u32_const(bindings::LINUX_ETIME);
273    pub const ENOSR: Self = Self::from_u32_const(bindings::LINUX_ENOSR);
274    pub const ENONET: Self = Self::from_u32_const(bindings::LINUX_ENONET);
275    pub const ENOPKG: Self = Self::from_u32_const(bindings::LINUX_ENOPKG);
276    pub const EREMOTE: Self = Self::from_u32_const(bindings::LINUX_EREMOTE);
277    pub const ENOLINK: Self = Self::from_u32_const(bindings::LINUX_ENOLINK);
278    pub const EADV: Self = Self::from_u32_const(bindings::LINUX_EADV);
279    pub const ESRMNT: Self = Self::from_u32_const(bindings::LINUX_ESRMNT);
280    pub const ECOMM: Self = Self::from_u32_const(bindings::LINUX_ECOMM);
281    pub const EPROTO: Self = Self::from_u32_const(bindings::LINUX_EPROTO);
282    pub const EMULTIHOP: Self = Self::from_u32_const(bindings::LINUX_EMULTIHOP);
283    pub const EDOTDOT: Self = Self::from_u32_const(bindings::LINUX_EDOTDOT);
284    pub const EBADMSG: Self = Self::from_u32_const(bindings::LINUX_EBADMSG);
285    pub const EOVERFLOW: Self = Self::from_u32_const(bindings::LINUX_EOVERFLOW);
286    pub const ENOTUNIQ: Self = Self::from_u32_const(bindings::LINUX_ENOTUNIQ);
287    pub const EBADFD: Self = Self::from_u32_const(bindings::LINUX_EBADFD);
288    pub const EREMCHG: Self = Self::from_u32_const(bindings::LINUX_EREMCHG);
289    pub const ELIBACC: Self = Self::from_u32_const(bindings::LINUX_ELIBACC);
290    pub const ELIBBAD: Self = Self::from_u32_const(bindings::LINUX_ELIBBAD);
291    pub const ELIBSCN: Self = Self::from_u32_const(bindings::LINUX_ELIBSCN);
292    pub const ELIBMAX: Self = Self::from_u32_const(bindings::LINUX_ELIBMAX);
293    pub const ELIBEXEC: Self = Self::from_u32_const(bindings::LINUX_ELIBEXEC);
294    pub const EILSEQ: Self = Self::from_u32_const(bindings::LINUX_EILSEQ);
295    pub const ERESTART: Self = Self::from_u32_const(bindings::LINUX_ERESTART);
296    pub const ESTRPIPE: Self = Self::from_u32_const(bindings::LINUX_ESTRPIPE);
297    pub const EUSERS: Self = Self::from_u32_const(bindings::LINUX_EUSERS);
298    pub const ENOTSOCK: Self = Self::from_u32_const(bindings::LINUX_ENOTSOCK);
299    pub const EDESTADDRREQ: Self = Self::from_u32_const(bindings::LINUX_EDESTADDRREQ);
300    pub const EMSGSIZE: Self = Self::from_u32_const(bindings::LINUX_EMSGSIZE);
301    pub const EPROTOTYPE: Self = Self::from_u32_const(bindings::LINUX_EPROTOTYPE);
302    pub const ENOPROTOOPT: Self = Self::from_u32_const(bindings::LINUX_ENOPROTOOPT);
303    pub const EPROTONOSUPPORT: Self = Self::from_u32_const(bindings::LINUX_EPROTONOSUPPORT);
304    pub const ESOCKTNOSUPPORT: Self = Self::from_u32_const(bindings::LINUX_ESOCKTNOSUPPORT);
305    pub const EOPNOTSUPP: Self = Self::from_u32_const(bindings::LINUX_EOPNOTSUPP);
306    pub const EPFNOSUPPORT: Self = Self::from_u32_const(bindings::LINUX_EPFNOSUPPORT);
307    pub const EAFNOSUPPORT: Self = Self::from_u32_const(bindings::LINUX_EAFNOSUPPORT);
308    pub const EADDRINUSE: Self = Self::from_u32_const(bindings::LINUX_EADDRINUSE);
309    pub const EADDRNOTAVAIL: Self = Self::from_u32_const(bindings::LINUX_EADDRNOTAVAIL);
310    pub const ENETDOWN: Self = Self::from_u32_const(bindings::LINUX_ENETDOWN);
311    pub const ENETUNREACH: Self = Self::from_u32_const(bindings::LINUX_ENETUNREACH);
312    pub const ENETRESET: Self = Self::from_u32_const(bindings::LINUX_ENETRESET);
313    pub const ECONNABORTED: Self = Self::from_u32_const(bindings::LINUX_ECONNABORTED);
314    pub const ECONNRESET: Self = Self::from_u32_const(bindings::LINUX_ECONNRESET);
315    pub const ENOBUFS: Self = Self::from_u32_const(bindings::LINUX_ENOBUFS);
316    pub const EISCONN: Self = Self::from_u32_const(bindings::LINUX_EISCONN);
317    pub const ENOTCONN: Self = Self::from_u32_const(bindings::LINUX_ENOTCONN);
318    pub const ESHUTDOWN: Self = Self::from_u32_const(bindings::LINUX_ESHUTDOWN);
319    pub const ETOOMANYREFS: Self = Self::from_u32_const(bindings::LINUX_ETOOMANYREFS);
320    pub const ETIMEDOUT: Self = Self::from_u32_const(bindings::LINUX_ETIMEDOUT);
321    pub const ECONNREFUSED: Self = Self::from_u32_const(bindings::LINUX_ECONNREFUSED);
322    pub const EHOSTDOWN: Self = Self::from_u32_const(bindings::LINUX_EHOSTDOWN);
323    pub const EHOSTUNREACH: Self = Self::from_u32_const(bindings::LINUX_EHOSTUNREACH);
324    pub const EALREADY: Self = Self::from_u32_const(bindings::LINUX_EALREADY);
325    pub const EINPROGRESS: Self = Self::from_u32_const(bindings::LINUX_EINPROGRESS);
326    pub const ESTALE: Self = Self::from_u32_const(bindings::LINUX_ESTALE);
327    pub const EUCLEAN: Self = Self::from_u32_const(bindings::LINUX_EUCLEAN);
328    pub const ENOTNAM: Self = Self::from_u32_const(bindings::LINUX_ENOTNAM);
329    pub const ENAVAIL: Self = Self::from_u32_const(bindings::LINUX_ENAVAIL);
330    pub const EISNAM: Self = Self::from_u32_const(bindings::LINUX_EISNAM);
331    pub const EREMOTEIO: Self = Self::from_u32_const(bindings::LINUX_EREMOTEIO);
332    pub const EDQUOT: Self = Self::from_u32_const(bindings::LINUX_EDQUOT);
333    pub const ENOMEDIUM: Self = Self::from_u32_const(bindings::LINUX_ENOMEDIUM);
334    pub const EMEDIUMTYPE: Self = Self::from_u32_const(bindings::LINUX_EMEDIUMTYPE);
335    pub const ECANCELED: Self = Self::from_u32_const(bindings::LINUX_ECANCELED);
336    pub const ENOKEY: Self = Self::from_u32_const(bindings::LINUX_ENOKEY);
337    pub const EKEYEXPIRED: Self = Self::from_u32_const(bindings::LINUX_EKEYEXPIRED);
338    pub const EKEYREVOKED: Self = Self::from_u32_const(bindings::LINUX_EKEYREVOKED);
339    pub const EKEYREJECTED: Self = Self::from_u32_const(bindings::LINUX_EKEYREJECTED);
340    pub const EOWNERDEAD: Self = Self::from_u32_const(bindings::LINUX_EOWNERDEAD);
341    pub const ENOTRECOVERABLE: Self = Self::from_u32_const(bindings::LINUX_ENOTRECOVERABLE);
342    pub const ERFKILL: Self = Self::from_u32_const(bindings::LINUX_ERFKILL);
343    pub const EHWPOISON: Self = Self::from_u32_const(bindings::LINUX_EHWPOISON);
344    pub const EINTR: Self = Self::from_u32_const(bindings::LINUX_EINTR);
345    pub const ENFILE: Self = Self::from_u32_const(bindings::LINUX_ENFILE);
346    pub const EPIPE: Self = Self::from_u32_const(bindings::LINUX_EPIPE);
347    pub const ESPIPE: Self = Self::from_u32_const(bindings::LINUX_ESPIPE);
348    pub const EBADF: Self = Self::from_u32_const(bindings::LINUX_EBADF);
349    pub const EPERM: Self = Self::from_u32_const(bindings::LINUX_EPERM);
350    pub const EFAULT: Self = Self::from_u32_const(bindings::LINUX_EFAULT);
351    pub const ESRCH: Self = Self::from_u32_const(bindings::LINUX_ESRCH);
352    pub const ENOENT: Self = Self::from_u32_const(bindings::LINUX_ENOENT);
353    pub const ENOTTY: Self = Self::from_u32_const(bindings::LINUX_ENOTTY);
354    pub const EEXIST: Self = Self::from_u32_const(bindings::LINUX_EEXIST);
355    pub const ECHILD: Self = Self::from_u32_const(bindings::LINUX_ECHILD);
356    pub const EACCES: Self = Self::from_u32_const(bindings::LINUX_EACCES);
357    pub const ENOEXEC: Self = Self::from_u32_const(bindings::LINUX_ENOEXEC);
358    pub const ENOTDIR: Self = Self::from_u32_const(bindings::LINUX_ENOTDIR);
359    // NOTE: add new entries to `errno_to_str` above
360
361    // Aliases
362    pub const EDEADLOCK: Self = Self::from_u32_const(bindings::LINUX_EDEADLOCK);
363    pub const EAGAIN: Self = Self::from_u32_const(bindings::LINUX_EAGAIN);
364    pub const ENOTSUP: Self = Self::EOPNOTSUPP;
365    pub const EFSBADCRC: Self = Self::from_u32_const(bindings::LINUX_EFSBADCRC);
366    pub const EFSCORRUPTED: Self = Self::from_u32_const(bindings::LINUX_EFSCORRUPTED);
367
368    /// From MAX_ERRNO in include/linux/err.h in kernel source. This doesn't
369    /// seem to be exposed in the installed kernel headers from which we generate bindings.
370    /// <https://github.com/torvalds/linux/blob/a4d7d701121981e3c3fe69ade376fe9f26324161/include/linux/err.h#L18>
371    pub const MAX: Self = Self(4095);
372
373    #[inline]
374    pub const fn from_u16(val: u16) -> Option<Self> {
375        const MAX: u16 = Errno::MAX.0;
376        match val {
377            1..=MAX => Some(Self(val)),
378            _ => None,
379        }
380    }
381
382    /// For C interop.
383    #[inline]
384    pub const fn to_negated_i64(self) -> i64 {
385        let val: u16 = self.0;
386        -(val as i64)
387    }
388
389    /// For C interop.
390    #[inline]
391    pub const fn to_negated_i32(self) -> i32 {
392        let val: u16 = self.0;
393        -(val as i32)
394    }
395
396    /// Primarily for checked conversion of bindings constants.
397    const fn from_u32_const(val: u32) -> Self {
398        let Some(rv) = Self::from_u16(val as u16) else {
399            panic!("Could not construct an `Errno`");
400        };
401        // check for truncation
402        assert!(rv.0 as u32 == val);
403        rv
404    }
405
406    /// Get libc's errno (global for the current thread).
407    #[cfg(feature = "libc")]
408    pub fn from_libc_errno() -> Self {
409        // SAFETY: The safety requirements for calling this function are
410        // undocumented, and I'm not aware of any.
411        let ptr = unsafe { libc::__errno_location() };
412        assert!(!ptr.is_null());
413        // SAFETY: We verified that `ptr` is non-NULL, and can only assume that
414        // libc gives us a pointer that is safe to dereference.
415        //
416        // `errno(2)` guarantees that it's thread-local, so there shouldn't be any
417        // data-races from other threads.
418        //
419        // A signal handler could run on the current thread and change the `errno`
420        // value at `*ptr`. A well-behaved handler should always restore the original
421        // value before returning (`signal-safety(7)`) which should make this
422        // sound; nonetheless we try to make the dereference "as atomic" as
423        // possible, e.g.  by directly dereferencing the pointer and not
424        // converting it to a Rust reference.
425        let raw = unsafe { *ptr };
426
427        Self::from_libc_errnum(raw)
428            .unwrap_or_else(|| panic!("Unexpected bad errno from libc: {raw}"))
429    }
430
431    /// Get a Result from the return value of a libc function that uses a
432    /// sentinel error value, and stores the errors themselves in errno.
433    #[cfg(feature = "libc")]
434    pub fn result_from_libc_errno<T>(sentinel: T, x: T) -> Result<T, Self>
435    where
436        T: Eq,
437    {
438        if x == sentinel {
439            Err(Self::from_libc_errno())
440        } else {
441            Ok(x)
442        }
443    }
444
445    /// Get a Result from a libc `errnum` return value, where 0 is used to
446    /// indicate "no error", and non-zero is an errno value. An example of such
447    /// a function is `libc::posix_spawn`.
448    ///
449    /// Panics if `errnum` is out of range. This shouldn't be the case for any `errnum` obtained
450    /// from libc APIs.
451    #[cfg(feature = "libc")]
452    pub fn result_from_libc_errnum(errnum: i32) -> Result<(), Self> {
453        if errnum == 0 {
454            Ok(())
455        } else {
456            Err(Self::from_libc_errnum(errnum)
457                .unwrap_or_else(|| panic!("errnum out of range: {errnum}")))
458        }
459    }
460
461    /// Convert from a libc error value. Returns `None` if out of range.
462    #[cfg(feature = "libc")]
463    pub fn from_libc_errnum(errnum: i32) -> Option<Self> {
464        // For now we assume that libc uses the same errnum values
465        // as the kernel. This isn't explicitly guaranteed, but we don't
466        // know of any exceptions in practice. In case it turns out not to be true
467        // we can either change this to a full explicit mapping, or handle
468        // individual known exceptions here.
469        Self::from_u16(u16::try_from(errnum).ok()?)
470    }
471}
472
473impl core::convert::From<linux_errno::Error> for Errno {
474    fn from(value: linux_errno::Error) -> Self {
475        // linux_errno::Error values should always be in range.
476        Self::try_from(value.get()).unwrap()
477    }
478}
479
480#[cfg(feature = "std")]
481impl core::convert::From<Errno> for std::io::Error {
482    fn from(e: Errno) -> Self {
483        Self::from_raw_os_error(e.into())
484    }
485}
486
487#[cfg(feature = "std")]
488impl core::convert::TryFrom<std::io::Error> for Errno {
489    type Error = std::io::Error;
490
491    fn try_from(e: std::io::Error) -> Result<Self, Self::Error> {
492        e.raw_os_error()
493            .and_then(|x| u16::try_from(x).ok())
494            .and_then(|x| x.try_into().ok())
495            .ok_or(e)
496    }
497}
498
499#[cfg(feature = "std")]
500impl std::error::Error for Errno {}