hermit/
errno.rs

1//! System error numbers.
2
3use core::convert::Infallible;
4
5use num_enum::{IntoPrimitive, TryFromPrimitive};
6use thiserror::Error;
7
8/// The error type for I/O operations and system calls.
9///
10/// The values of these error numbers are the same as in Linux.
11/// See [`asm-generic/errno-base.h`] and [`asm-generic/errno.h`] for details.
12///
13/// [`asm-generic/errno-base.h`]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/errno-base.h?h=v6.15
14/// [`asm-generic/errno.h`]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/errno.h?h=v6.15
15#[derive(Error, TryFromPrimitive, IntoPrimitive, PartialEq, Eq, Clone, Copy, Debug)]
16#[repr(i32)]
17pub enum Errno {
18	/// Operation not permitted
19	#[doc(alias = "EPERM")]
20	#[error("Operation not permitted")]
21	Perm = 1,
22
23	/// No such file or directory
24	#[doc(alias = "ENOENT")]
25	#[error("No such file or directory")]
26	Noent = 2,
27
28	/// No such process
29	#[doc(alias = "ESRCH")]
30	#[error("No such process")]
31	Srch = 3,
32
33	/// Interrupted system call
34	#[doc(alias = "EINTR")]
35	#[error("Interrupted system call")]
36	Intr = 4,
37
38	/// I/O error
39	#[doc(alias = "EIO")]
40	#[error("I/O error")]
41	Io = 5,
42
43	/// No such device or address
44	#[doc(alias = "ENXIO")]
45	#[error("No such device or address")]
46	Nxio = 6,
47
48	/// Argument list too long
49	#[doc(alias = "E2BIG")]
50	#[error("Argument list too long")]
51	Toobig = 7,
52
53	/// Exec format error
54	#[doc(alias = "ENOEXEC")]
55	#[error("Exec format error")]
56	Noexec = 8,
57
58	/// Bad file number
59	#[doc(alias = "EBADF")]
60	#[error("Bad file number")]
61	Badf = 9,
62
63	/// No child processes
64	#[doc(alias = "ECHILD")]
65	#[error("No child processes")]
66	Child = 10,
67
68	/// Try again
69	#[doc(alias = "EAGAIN")]
70	#[error("Try again")]
71	Again = 11,
72
73	/// Out of memory
74	#[doc(alias = "ENOMEM")]
75	#[error("Out of memory")]
76	Nomem = 12,
77
78	/// Permission denied
79	#[doc(alias = "EACCES")]
80	#[error("Permission denied")]
81	Acces = 13,
82
83	/// Bad address
84	#[doc(alias = "EFAULT")]
85	#[error("Bad address")]
86	Fault = 14,
87
88	/// Block device required
89	#[doc(alias = "ENOTBLK")]
90	#[error("Block device required")]
91	Notblk = 15,
92
93	/// Device or resource busy
94	#[doc(alias = "EBUSY")]
95	#[error("Device or resource busy")]
96	Busy = 16,
97
98	/// File exists
99	#[doc(alias = "EEXIST")]
100	#[error("File exists")]
101	Exist = 17,
102
103	/// Cross-device link
104	#[doc(alias = "EXDEV")]
105	#[error("Cross-device link")]
106	Xdev = 18,
107
108	/// No such device
109	#[doc(alias = "ENODEV")]
110	#[error("No such device")]
111	Nodev = 19,
112
113	/// Not a directory
114	#[doc(alias = "ENOTDIR")]
115	#[error("Not a directory")]
116	Notdir = 20,
117
118	/// Is a directory
119	#[doc(alias = "EISDIR")]
120	#[error("Is a directory")]
121	Isdir = 21,
122
123	/// Invalid argument
124	#[doc(alias = "EINVAL")]
125	#[error("Invalid argument")]
126	Inval = 22,
127
128	/// File table overflow
129	#[doc(alias = "ENFILE")]
130	#[error("File table overflow")]
131	Nfile = 23,
132
133	/// Too many open files
134	#[doc(alias = "EMFILE")]
135	#[error("Too many open files")]
136	Mfile = 24,
137
138	/// Not a typewriter
139	#[doc(alias = "ENOTTY")]
140	#[error("Not a typewriter")]
141	Notty = 25,
142
143	/// Text file busy
144	#[doc(alias = "ETXTBSY")]
145	#[error("Text file busy")]
146	Txtbsy = 26,
147
148	/// File too large
149	#[doc(alias = "EFBIG")]
150	#[error("File too large")]
151	Fbig = 27,
152
153	/// No space left on device
154	#[doc(alias = "ENOSPC")]
155	#[error("No space left on device")]
156	Nospc = 28,
157
158	/// Illegal seek
159	#[doc(alias = "ESPIPE")]
160	#[error("Illegal seek")]
161	Spipe = 29,
162
163	/// Read-only file system
164	#[doc(alias = "EROFS")]
165	#[error("Read-only file system")]
166	Rofs = 30,
167
168	/// Too many links
169	#[doc(alias = "EMLINK")]
170	#[error("Too many links")]
171	Mlink = 31,
172
173	/// Broken pipe
174	#[doc(alias = "EPIPE")]
175	#[error("Broken pipe")]
176	Pipe = 32,
177
178	/// Math argument out of domain of func
179	#[doc(alias = "EDOM")]
180	#[error("Math argument out of domain of func")]
181	Dom = 33,
182
183	/// Math result not representable
184	#[doc(alias = "ERANGE")]
185	#[error("Math result not representable")]
186	Range = 34,
187
188	/// Resource deadlock would occur
189	#[doc(alias = "EDEADLK")]
190	#[error("Resource deadlock would occur")]
191	Deadlk = 35,
192
193	/// File name too long
194	#[doc(alias = "ENAMETOOLONG")]
195	#[error("File name too long")]
196	Nametoolong = 36,
197
198	/// No record locks available
199	#[doc(alias = "ENOLCK")]
200	#[error("No record locks available")]
201	Nolck = 37,
202
203	/// Invalid system call number
204	#[doc(alias = "ENOSYS")]
205	#[error("Invalid system call number")]
206	Nosys = 38,
207
208	/// Directory not empty
209	#[doc(alias = "ENOTEMPTY")]
210	#[error("Directory not empty")]
211	Notempty = 39,
212
213	/// Too many symbolic links encountered
214	#[doc(alias = "ELOOP")]
215	#[error("Too many symbolic links encountered")]
216	Loop = 40,
217
218	/// No message of desired type
219	#[doc(alias = "ENOMSG")]
220	#[error("No message of desired type")]
221	Nomsg = 42,
222
223	/// Identifier removed
224	#[doc(alias = "EIDRM")]
225	#[error("Identifier removed")]
226	Idrm = 43,
227
228	/// Channel number out of range
229	#[doc(alias = "ECHRNG")]
230	#[error("Channel number out of range")]
231	Chrng = 44,
232
233	/// Level 2 not synchronized
234	#[doc(alias = "EL2NSYNC")]
235	#[error("Level 2 not synchronized")]
236	L2nsync = 45,
237
238	/// Level 3 halted
239	#[doc(alias = "EL3HLT")]
240	#[error("Level 3 halted")]
241	L3hlt = 46,
242
243	/// Level 3 reset
244	#[doc(alias = "EL3RST")]
245	#[error("Level 3 reset")]
246	L3rst = 47,
247
248	/// Link number out of range
249	#[doc(alias = "ELNRNG")]
250	#[error("Link number out of range")]
251	Lnrng = 48,
252
253	/// Protocol driver not attached
254	#[doc(alias = "EUNATCH")]
255	#[error("Protocol driver not attached")]
256	Unatch = 49,
257
258	/// No CSI structure available
259	#[doc(alias = "ENOCSI")]
260	#[error("No CSI structure available")]
261	Nocsi = 50,
262
263	/// Level 2 halted
264	#[doc(alias = "EL2HLT")]
265	#[error("Level 2 halted")]
266	L2hlt = 51,
267
268	/// Invalid exchange
269	#[doc(alias = "EBADE")]
270	#[error("Invalid exchange")]
271	Bade = 52,
272
273	/// Invalid request descriptor
274	#[doc(alias = "EBADR")]
275	#[error("Invalid request descriptor")]
276	Badr = 53,
277
278	/// Exchange full
279	#[doc(alias = "EXFULL")]
280	#[error("Exchange full")]
281	Xfull = 54,
282
283	/// No anode
284	#[doc(alias = "ENOANO")]
285	#[error("No anode")]
286	Noano = 55,
287
288	/// Invalid request code
289	#[doc(alias = "EBADRQC")]
290	#[error("Invalid request code")]
291	Badrqc = 56,
292
293	/// Invalid slot
294	#[doc(alias = "EBADSLT")]
295	#[error("Invalid slot")]
296	Badslt = 57,
297
298	/// Bad font file format
299	#[doc(alias = "EBFONT")]
300	#[error("Bad font file format")]
301	Bfont = 59,
302
303	/// Device not a stream
304	#[doc(alias = "ENOSTR")]
305	#[error("Device not a stream")]
306	Nostr = 60,
307
308	/// No data available
309	#[doc(alias = "ENODATA")]
310	#[error("No data available")]
311	Nodata = 61,
312
313	/// Timer expired
314	#[doc(alias = "ETIME")]
315	#[error("Timer expired")]
316	Time = 62,
317
318	/// Out of streams resources
319	#[doc(alias = "ENOSR")]
320	#[error("Out of streams resources")]
321	Nosr = 63,
322
323	/// Machine is not on the network
324	#[doc(alias = "ENONET")]
325	#[error("Machine is not on the network")]
326	Nonet = 64,
327
328	/// Package not installed
329	#[doc(alias = "ENOPKG")]
330	#[error("Package not installed")]
331	Nopkg = 65,
332
333	/// Object is remote
334	#[doc(alias = "EREMOTE")]
335	#[error("Object is remote")]
336	Remote = 66,
337
338	/// Link has been severed
339	#[doc(alias = "ENOLINK")]
340	#[error("Link has been severed")]
341	Nolink = 67,
342
343	/// Advertise error
344	#[doc(alias = "EADV")]
345	#[error("Advertise error")]
346	Adv = 68,
347
348	/// Srmount error
349	#[doc(alias = "ESRMNT")]
350	#[error("Srmount error")]
351	Srmnt = 69,
352
353	/// Communication error on send
354	#[doc(alias = "ECOMM")]
355	#[error("Communication error on send")]
356	Comm = 70,
357
358	/// Protocol error
359	#[doc(alias = "EPROTO")]
360	#[error("Protocol error")]
361	Proto = 71,
362
363	/// Multihop attempted
364	#[doc(alias = "EMULTIHOP")]
365	#[error("Multihop attempted")]
366	Multihop = 72,
367
368	/// RFS specific error
369	#[doc(alias = "EDOTDOT")]
370	#[error("RFS specific error")]
371	Dotdot = 73,
372
373	/// Not a data message
374	#[doc(alias = "EBADMSG")]
375	#[error("Not a data message")]
376	Badmsg = 74,
377
378	/// Value too large for defined data type
379	#[doc(alias = "EOVERFLOW")]
380	#[error("Value too large for defined data type")]
381	Overflow = 75,
382
383	/// Name not unique on network
384	#[doc(alias = "ENOTUNIQ")]
385	#[error("Name not unique on network")]
386	Notuniq = 76,
387
388	/// File descriptor in bad state
389	#[doc(alias = "EBADFD")]
390	#[error("File descriptor in bad state")]
391	Badfd = 77,
392
393	/// Remote address changed
394	#[doc(alias = "EREMCHG")]
395	#[error("Remote address changed")]
396	Remchg = 78,
397
398	/// Can not access a needed shared library
399	#[doc(alias = "ELIBACC")]
400	#[error("Can not access a needed shared library")]
401	Libacc = 79,
402
403	/// Accessing a corrupted shared library
404	#[doc(alias = "ELIBBAD")]
405	#[error("Accessing a corrupted shared library")]
406	Libbad = 80,
407
408	/// .lib section in a.out corrupted
409	#[doc(alias = "ELIBSCN")]
410	#[error(".lib section in a.out corrupted")]
411	Libscn = 81,
412
413	/// Attempting to link in too many shared libraries
414	#[doc(alias = "ELIBMAX")]
415	#[error("Attempting to link in too many shared libraries")]
416	Libmax = 82,
417
418	/// Cannot exec a shared library directly
419	#[doc(alias = "ELIBEXEC")]
420	#[error("Cannot exec a shared library directly")]
421	Libexec = 83,
422
423	/// Illegal byte sequence
424	#[doc(alias = "EILSEQ")]
425	#[error("Illegal byte sequence")]
426	Ilseq = 84,
427
428	/// Interrupted system call should be restarted
429	#[doc(alias = "ERESTART")]
430	#[error("Interrupted system call should be restarted")]
431	Restart = 85,
432
433	/// Streams pipe error
434	#[doc(alias = "ESTRPIPE")]
435	#[error("Streams pipe error")]
436	Strpipe = 86,
437
438	/// Too many users
439	#[doc(alias = "EUSERS")]
440	#[error("Too many users")]
441	Users = 87,
442
443	/// Socket operation on non-socket
444	#[doc(alias = "ENOTSOCK")]
445	#[error("Socket operation on non-socket")]
446	Notsock = 88,
447
448	/// Destination address required
449	#[doc(alias = "EDESTADDRREQ")]
450	#[error("Destination address required")]
451	Destaddrreq = 89,
452
453	/// Message too long
454	#[doc(alias = "EMSGSIZE")]
455	#[error("Message too long")]
456	Msgsize = 90,
457
458	/// Protocol wrong type for socket
459	#[doc(alias = "EPROTOTYPE")]
460	#[error("Protocol wrong type for socket")]
461	Prototype = 91,
462
463	/// Protocol not available
464	#[doc(alias = "ENOPROTOOPT")]
465	#[error("Protocol not available")]
466	Noprotoopt = 92,
467
468	/// Protocol not supported
469	#[doc(alias = "EPROTONOSUPPORT")]
470	#[error("Protocol not supported")]
471	Protonosupport = 93,
472
473	/// Socket type not supported
474	#[doc(alias = "ESOCKTNOSUPPORT")]
475	#[error("Socket type not supported")]
476	Socktnosupport = 94,
477
478	/// Operation not supported on transport endpoint
479	#[doc(alias = "EOPNOTSUPP")]
480	#[error("Operation not supported on transport endpoint")]
481	Opnotsupp = 95,
482
483	/// Protocol family not supported
484	#[doc(alias = "EPFNOSUPPORT")]
485	#[error("Protocol family not supported")]
486	Pfnosupport = 96,
487
488	/// Address family not supported by protocol
489	#[doc(alias = "EAFNOSUPPORT")]
490	#[error("Address family not supported by protocol")]
491	Afnosupport = 97,
492
493	/// Address already in use
494	#[doc(alias = "EADDRINUSE")]
495	#[error("Address already in use")]
496	Addrinuse = 98,
497
498	/// Cannot assign requested address
499	#[doc(alias = "EADDRNOTAVAIL")]
500	#[error("Cannot assign requested address")]
501	Addrnotavail = 99,
502
503	/// Network is down
504	#[doc(alias = "ENETDOWN")]
505	#[error("Network is down")]
506	Netdown = 100,
507
508	/// Network is unreachable
509	#[doc(alias = "ENETUNREACH")]
510	#[error("Network is unreachable")]
511	Netunreach = 101,
512
513	/// Network dropped connection because of reset
514	#[doc(alias = "ENETRESET")]
515	#[error("Network dropped connection because of reset")]
516	Netreset = 102,
517
518	/// Software caused connection abort
519	#[doc(alias = "ECONNABORTED")]
520	#[error("Software caused connection abort")]
521	Connaborted = 103,
522
523	/// Connection reset by peer
524	#[doc(alias = "ECONNRESET")]
525	#[error("Connection reset by peer")]
526	Connreset = 104,
527
528	/// No buffer space available
529	#[doc(alias = "ENOBUFS")]
530	#[error("No buffer space available")]
531	Nobufs = 105,
532
533	/// Transport endpoint is already connected
534	#[doc(alias = "EISCONN")]
535	#[error("Transport endpoint is already connected")]
536	Isconn = 106,
537
538	/// Transport endpoint is not connected
539	#[doc(alias = "ENOTCONN")]
540	#[error("Transport endpoint is not connected")]
541	Notconn = 107,
542
543	/// Cannot send after transport endpoint shutdown
544	#[doc(alias = "ESHUTDOWN")]
545	#[error("Cannot send after transport endpoint shutdown")]
546	Shutdown = 108,
547
548	/// Too many references: cannot splice
549	#[doc(alias = "ETOOMANYREFS")]
550	#[error("Too many references: cannot splice")]
551	Toomanyrefs = 109,
552
553	/// Connection timed out
554	#[doc(alias = "ETIMEDOUT")]
555	#[error("Connection timed out")]
556	Timedout = 110,
557
558	/// Connection refused
559	#[doc(alias = "ECONNREFUSED")]
560	#[error("Connection refused")]
561	Connrefused = 111,
562
563	/// Host is down
564	#[doc(alias = "EHOSTDOWN")]
565	#[error("Host is down")]
566	Hostdown = 112,
567
568	/// No route to host
569	#[doc(alias = "EHOSTUNREACH")]
570	#[error("No route to host")]
571	Hostunreach = 113,
572
573	/// Operation already in progress
574	#[doc(alias = "EALREADY")]
575	#[error("Operation already in progress")]
576	Already = 114,
577
578	/// Operation now in progress
579	#[doc(alias = "EINPROGRESS")]
580	#[error("Operation now in progress")]
581	Inprogress = 115,
582
583	/// Stale file handle
584	#[doc(alias = "ESTALE")]
585	#[error("Stale file handle")]
586	Stale = 116,
587
588	/// Structure needs cleaning
589	#[doc(alias = "EUCLEAN")]
590	#[error("Structure needs cleaning")]
591	Uclean = 117,
592
593	/// Not a XENIX named type file
594	#[doc(alias = "ENOTNAM")]
595	#[error("Not a XENIX named type file")]
596	Notnam = 118,
597
598	/// No XENIX semaphores available
599	#[doc(alias = "ENAVAIL")]
600	#[error("No XENIX semaphores available")]
601	Navail = 119,
602
603	/// Is a named type file
604	#[doc(alias = "EISNAM")]
605	#[error("Is a named type file")]
606	Isnam = 120,
607
608	/// Remote I/O error
609	#[doc(alias = "EREMOTEIO")]
610	#[error("Remote I/O error")]
611	Remoteio = 121,
612
613	/// Quota exceeded
614	#[doc(alias = "EDQUOT")]
615	#[error("Quota exceeded")]
616	Dquot = 122,
617
618	/// No medium found
619	#[doc(alias = "ENOMEDIUM")]
620	#[error("No medium found")]
621	Nomedium = 123,
622
623	/// Wrong medium type
624	#[doc(alias = "EMEDIUMTYPE")]
625	#[error("Wrong medium type")]
626	Mediumtype = 124,
627
628	/// Operation Canceled
629	#[doc(alias = "ECANCELED")]
630	#[error("Operation Canceled")]
631	Canceled = 125,
632
633	/// Required key not available
634	#[doc(alias = "ENOKEY")]
635	#[error("Required key not available")]
636	Nokey = 126,
637
638	/// Key has expired
639	#[doc(alias = "EKEYEXPIRED")]
640	#[error("Key has expired")]
641	Keyexpired = 127,
642
643	/// Key has been revoked
644	#[doc(alias = "EKEYREVOKED")]
645	#[error("Key has been revoked")]
646	Keyrevoked = 128,
647
648	/// Key was rejected by service
649	#[doc(alias = "EKEYREJECTED")]
650	#[error("Key was rejected by service")]
651	Keyrejected = 129,
652
653	/// Owner died
654	#[doc(alias = "EOWNERDEAD")]
655	#[error("Owner died")]
656	Ownerdead = 130,
657
658	/// State not recoverable
659	#[doc(alias = "ENOTRECOVERABLE")]
660	#[error("State not recoverable")]
661	Notrecoverable = 131,
662
663	/// Operation not possible due to RF-kill
664	#[doc(alias = "ERFKILL")]
665	#[error("Operation not possible due to RF-kill")]
666	Rfkill = 132,
667
668	/// Memory page has hardware error
669	#[doc(alias = "EHWPOISON")]
670	#[error("Memory page has hardware error")]
671	Hwpoison = 133,
672}
673
674impl From<Infallible> for Errno {
675	fn from(value: Infallible) -> Self {
676		match value {}
677	}
678}
679
680/// Returns the pointer to `errno`.
681#[cfg(all(
682	not(any(feature = "common-os", feature = "nostd")),
683	not(target_arch = "riscv64"),
684))]
685#[unsafe(no_mangle)]
686#[linkage = "weak"]
687pub extern "C" fn sys_errno_location() -> *mut i32 {
688	use core::cell::UnsafeCell;
689
690	#[thread_local]
691	static ERRNO: UnsafeCell<i32> = UnsafeCell::new(0);
692
693	ERRNO.get()
694}
695
696/// Get the error number from the thread local storage
697///
698/// Soft-deprecated in favor of using `sys_errno_location`.
699#[cfg(not(feature = "nostd"))]
700#[unsafe(no_mangle)]
701pub extern "C" fn sys_get_errno() -> i32 {
702	sys_errno()
703}
704
705/// Get the error number from the thread local storage
706///
707/// Soft-deprecated in favor of using `sys_errno_location`.
708#[cfg(not(feature = "nostd"))]
709#[unsafe(no_mangle)]
710pub extern "C" fn sys_errno() -> i32 {
711	cfg_if::cfg_if! {
712		if #[cfg(any(feature = "common-os", target_arch = "riscv64"))] {
713			0
714		} else {
715			unsafe { *sys_errno_location() }
716		}
717	}
718}
719
720pub(crate) trait ToErrno {
721	fn to_errno(&self) -> Option<i32> {
722		None
723	}
724
725	fn set_errno(self) -> Self
726	where
727		Self: Sized,
728	{
729		if let Some(errno) = self.to_errno() {
730			cfg_if::cfg_if! {
731				if #[cfg(any(feature = "common-os", feature = "nostd", target_arch = "riscv64"))] {
732					let _ = errno;
733				} else {
734					unsafe {
735						*sys_errno_location() = errno;
736					}
737				}
738			}
739		}
740		self
741	}
742}
743
744impl ToErrno for i32 {
745	fn to_errno(&self) -> Option<i32> {
746		(*self < 0).then_some(-self)
747	}
748}
749
750impl ToErrno for i64 {
751	fn to_errno(&self) -> Option<i32> {
752		(*self < 0).then(|| i32::try_from(-self).unwrap())
753	}
754}
755
756impl ToErrno for isize {
757	fn to_errno(&self) -> Option<i32> {
758		(*self < 0).then(|| i32::try_from(-self).unwrap())
759	}
760}
761
762impl ToErrno for Errno {
763	fn to_errno(&self) -> Option<i32> {
764		Some(i32::from(*self))
765	}
766}
767
768impl ToErrno for u8 {}
769impl ToErrno for u16 {}
770impl ToErrno for u32 {}
771impl ToErrno for usize {}
772impl ToErrno for *mut u8 {}
773impl ToErrno for () {}
774impl ToErrno for ! {}