hermit/
errno.rs

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