1 //! The `rustix` `Errno` type. 2 //! 3 //! This type holds an OS error code, which conceptually corresponds to an 4 //! `errno` value. 5 //! 6 //! # Safety 7 //! 8 //! Linux uses error codes in `-4095..0`; we use rustc attributes to describe 9 //! this restricted range of values. 10 #![allow(unsafe_code)] 11 #![cfg_attr(not(rustc_attrs), allow(unused_unsafe))] 12 13 use super::super::c; 14 use crate::backend::fd::RawFd; 15 use crate::backend::reg::{RetNumber, RetReg}; 16 use crate::io; 17 use linux_raw_sys::errno; 18 19 /// The error type for `rustix` APIs. 20 /// 21 /// This is similar to `std::io::Error`, but only holds an OS error code, 22 /// and no extra error value. 23 #[repr(transparent)] 24 #[doc(alias = "errno")] 25 #[derive(Eq, PartialEq, Hash, Copy, Clone)] 26 // Linux returns negated error codes, and we leave them in negated form, so 27 // error codes are in `-4095..0`. 28 #[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0xf001))] 29 #[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xffff))] 30 pub struct Errno(u16); 31 32 impl Errno { 33 /// Extract an `Errno` value from a `std::io::Error`. 34 /// 35 /// This isn't a `From` conversion because it's expected to be relatively 36 /// uncommon. 37 #[cfg(feature = "std")] 38 #[inline] from_io_errornull39 pub fn from_io_error(io_err: &std::io::Error) -> Option<Self> { 40 io_err.raw_os_error().and_then(|raw| { 41 // `std::io::Error` could theoretically have arbitrary "OS error" 42 // values, so check that they're in Linux's range. 43 if (1..4096).contains(&raw) { 44 Some(Self::from_errno(raw as u32)) 45 } else { 46 None 47 } 48 }) 49 } 50 51 /// Extract the raw OS error number from this error. 52 #[inline] 53 pub const fn raw_os_error(self) -> i32 { 54 (self.0 as i16 as i32).wrapping_neg() 55 } 56 57 /// Construct an `Errno` from a raw OS error number. 58 #[inline] 59 pub const fn from_raw_os_error(raw: i32) -> Self { 60 Self::from_errno(raw as u32) 61 } 62 63 /// Convert from a C errno value (which is positive) to an `Errno`. 64 const fn from_errno(raw: u32) -> Self { 65 // We store error values in negated form, so that we don't have to negate 66 // them after every syscall. 67 let encoded = raw.wrapping_neg() as u16; 68 69 // TODO: Use Range::contains, once that's `const`. 70 const_assert!(encoded >= 0xf001); 71 72 // Safety: Linux syscalls return negated error values in the range 73 // `-4095..0`, which we just asserted. 74 unsafe { Self(encoded) } 75 } 76 } 77 78 /// Check for an error from the result of a syscall which encodes a 79 /// `c::c_int` on success. 80 #[inline] 81 pub(in crate::backend) fn try_decode_c_int<Num: RetNumber>( 82 raw: RetReg<Num>, 83 ) -> io::Result<c::c_int> { 84 if raw.is_in_range(-4095..0) { 85 // Safety: `raw` must be in `-4095..0`, and we just checked that raw is 86 // in that range. 87 return Err(unsafe { Errno(raw.decode_error_code()) }); 88 } 89 90 Ok(raw.decode_c_int()) 91 } 92 93 /// Check for an error from the result of a syscall which encodes a 94 /// `c::c_uint` on success. 95 #[inline] 96 pub(in crate::backend) fn try_decode_c_uint<Num: RetNumber>( 97 raw: RetReg<Num>, 98 ) -> io::Result<c::c_uint> { 99 if raw.is_in_range(-4095..0) { 100 // Safety: `raw` must be in `-4095..0`, and we just checked that raw is 101 // in that range. 102 return Err(unsafe { Errno(raw.decode_error_code()) }); 103 } 104 105 Ok(raw.decode_c_uint()) 106 } 107 108 /// Check for an error from the result of a syscall which encodes a `usize` on 109 /// success. 110 #[inline] 111 pub(in crate::backend) fn try_decode_usize<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<usize> { 112 if raw.is_in_range(-4095..0) { 113 // Safety: `raw` must be in `-4095..0`, and we just checked that raw is 114 // in that range. 115 return Err(unsafe { Errno(raw.decode_error_code()) }); 116 } 117 118 Ok(raw.decode_usize()) 119 } 120 121 /// Check for an error from the result of a syscall which encodes a 122 /// `*mut c_void` on success. 123 #[inline] 124 pub(in crate::backend) fn try_decode_void_star<Num: RetNumber>( 125 raw: RetReg<Num>, 126 ) -> io::Result<*mut c::c_void> { 127 if raw.is_in_range(-4095..0) { 128 // Safety: `raw` must be in `-4095..0`, and we just checked that raw is 129 // in that range. 130 return Err(unsafe { Errno(raw.decode_error_code()) }); 131 } 132 133 Ok(raw.decode_void_star()) 134 } 135 136 /// Check for an error from the result of a syscall which encodes a 137 /// `u64` on success. 138 #[cfg(target_pointer_width = "64")] 139 #[inline] 140 pub(in crate::backend) fn try_decode_u64<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<u64> { 141 if raw.is_in_range(-4095..0) { 142 // Safety: `raw` must be in `-4095..0`, and we just checked that raw is 143 // in that range. 144 return Err(unsafe { Errno(raw.decode_error_code()) }); 145 } 146 147 Ok(raw.decode_u64()) 148 } 149 150 /// Check for an error from the result of a syscall which encodes a file 151 /// descriptor on success. 152 /// 153 /// # Safety 154 /// 155 /// This must only be used with syscalls which return file descriptors on 156 /// success. 157 #[inline] 158 pub(in crate::backend) unsafe fn try_decode_raw_fd<Num: RetNumber>( 159 raw: RetReg<Num>, 160 ) -> io::Result<RawFd> { 161 // Instead of using `check_result` here, we just check for negative, since 162 // this function is only used for system calls which return file 163 // descriptors, and this produces smaller code. 164 if raw.is_negative() { 165 debug_assert!(raw.is_in_range(-4095..0)); 166 167 // Tell the optimizer that we know the value is in the error range. 168 // This helps it avoid unnecessary integer conversions. 169 #[cfg(core_intrinsics)] 170 { 171 core::intrinsics::assume(raw.is_in_range(-4095..0)); 172 } 173 174 return Err(Errno(raw.decode_error_code())); 175 } 176 177 Ok(raw.decode_raw_fd()) 178 } 179 180 /// Check for an error from the result of a syscall which encodes no value on 181 /// success. On success, return the unconsumed `raw` value. 182 /// 183 /// # Safety 184 /// 185 /// This must only be used with syscalls which return no value on success. 186 #[inline] 187 pub(in crate::backend) unsafe fn try_decode_void<Num: RetNumber>( 188 raw: RetReg<Num>, 189 ) -> io::Result<()> { 190 // Instead of using `check_result` here, we just check for zero, since this 191 // function is only used for system calls which have no other return value, 192 // and this produces smaller code. 193 if raw.is_nonzero() { 194 debug_assert!(raw.is_in_range(-4095..0)); 195 196 // Tell the optimizer that we know the value is in the error range. 197 // This helps it avoid unnecessary integer conversions. 198 #[cfg(core_intrinsics)] 199 { 200 core::intrinsics::assume(raw.is_in_range(-4095..0)); 201 } 202 203 return Err(Errno(raw.decode_error_code())); 204 } 205 206 raw.decode_void(); 207 208 Ok(()) 209 } 210 211 /// Check for an error from the result of a syscall which does not return on 212 /// success. On success, return the unconsumed `raw` value. 213 /// 214 /// # Safety 215 /// 216 /// This must only be used with syscalls which do not return on success. 217 #[cfg(feature = "runtime")] 218 #[inline] 219 pub(in crate::backend) unsafe fn try_decode_error<Num: RetNumber>(raw: RetReg<Num>) -> io::Errno { 220 debug_assert!(raw.is_in_range(-4095..0)); 221 222 // Tell the optimizer that we know the value is in the error range. 223 // This helps it avoid unnecessary integer conversions. 224 #[cfg(core_intrinsics)] 225 { 226 core::intrinsics::assume(raw.is_in_range(-4095..0)); 227 } 228 229 Errno(raw.decode_error_code()) 230 } 231 232 /// Return the contained `usize` value. 233 #[cfg(not(debug_assertions))] 234 #[inline] 235 pub(in crate::backend) fn decode_usize_infallible<Num: RetNumber>(raw: RetReg<Num>) -> usize { 236 raw.decode_usize() 237 } 238 239 impl Errno { 240 /// `EACCES` 241 #[doc(alias = "ACCES")] 242 pub const ACCESS: Self = Self::from_errno(errno::EACCES); 243 /// `EADDRINUSE` 244 pub const ADDRINUSE: Self = Self::from_errno(errno::EADDRINUSE); 245 /// `EADDRNOTAVAIL` 246 pub const ADDRNOTAVAIL: Self = Self::from_errno(errno::EADDRNOTAVAIL); 247 /// `EADV` 248 pub const ADV: Self = Self::from_errno(errno::EADV); 249 /// `EAFNOSUPPORT` 250 pub const AFNOSUPPORT: Self = Self::from_errno(errno::EAFNOSUPPORT); 251 /// `EAGAIN` 252 pub const AGAIN: Self = Self::from_errno(errno::EAGAIN); 253 /// `EALREADY` 254 pub const ALREADY: Self = Self::from_errno(errno::EALREADY); 255 /// `EBADE` 256 pub const BADE: Self = Self::from_errno(errno::EBADE); 257 /// `EBADF` 258 pub const BADF: Self = Self::from_errno(errno::EBADF); 259 /// `EBADFD` 260 pub const BADFD: Self = Self::from_errno(errno::EBADFD); 261 /// `EBADMSG` 262 pub const BADMSG: Self = Self::from_errno(errno::EBADMSG); 263 /// `EBADR` 264 pub const BADR: Self = Self::from_errno(errno::EBADR); 265 /// `EBADRQC` 266 pub const BADRQC: Self = Self::from_errno(errno::EBADRQC); 267 /// `EBADSLT` 268 pub const BADSLT: Self = Self::from_errno(errno::EBADSLT); 269 /// `EBFONT` 270 pub const BFONT: Self = Self::from_errno(errno::EBFONT); 271 /// `EBUSY` 272 pub const BUSY: Self = Self::from_errno(errno::EBUSY); 273 /// `ECANCELED` 274 pub const CANCELED: Self = Self::from_errno(errno::ECANCELED); 275 /// `ECHILD` 276 pub const CHILD: Self = Self::from_errno(errno::ECHILD); 277 /// `ECHRNG` 278 pub const CHRNG: Self = Self::from_errno(errno::ECHRNG); 279 /// `ECOMM` 280 pub const COMM: Self = Self::from_errno(errno::ECOMM); 281 /// `ECONNABORTED` 282 pub const CONNABORTED: Self = Self::from_errno(errno::ECONNABORTED); 283 /// `ECONNREFUSED` 284 pub const CONNREFUSED: Self = Self::from_errno(errno::ECONNREFUSED); 285 /// `ECONNRESET` 286 pub const CONNRESET: Self = Self::from_errno(errno::ECONNRESET); 287 /// `EDEADLK` 288 pub const DEADLK: Self = Self::from_errno(errno::EDEADLK); 289 /// `EDEADLOCK` 290 pub const DEADLOCK: Self = Self::from_errno(errno::EDEADLOCK); 291 /// `EDESTADDRREQ` 292 pub const DESTADDRREQ: Self = Self::from_errno(errno::EDESTADDRREQ); 293 /// `EDOM` 294 pub const DOM: Self = Self::from_errno(errno::EDOM); 295 /// `EDOTDOT` 296 pub const DOTDOT: Self = Self::from_errno(errno::EDOTDOT); 297 /// `EDQUOT` 298 pub const DQUOT: Self = Self::from_errno(errno::EDQUOT); 299 /// `EEXIST` 300 pub const EXIST: Self = Self::from_errno(errno::EEXIST); 301 /// `EFAULT` 302 pub const FAULT: Self = Self::from_errno(errno::EFAULT); 303 /// `EFBIG` 304 pub const FBIG: Self = Self::from_errno(errno::EFBIG); 305 /// `EHOSTDOWN` 306 pub const HOSTDOWN: Self = Self::from_errno(errno::EHOSTDOWN); 307 /// `EHOSTUNREACH` 308 pub const HOSTUNREACH: Self = Self::from_errno(errno::EHOSTUNREACH); 309 /// `EHWPOISON` 310 pub const HWPOISON: Self = Self::from_errno(errno::EHWPOISON); 311 /// `EIDRM` 312 pub const IDRM: Self = Self::from_errno(errno::EIDRM); 313 /// `EILSEQ` 314 pub const ILSEQ: Self = Self::from_errno(errno::EILSEQ); 315 /// `EINPROGRESS` 316 pub const INPROGRESS: Self = Self::from_errno(errno::EINPROGRESS); 317 /// `EINTR`. 318 /// 319 /// For a convenient way to retry system calls that exit with `INTR`, use 320 /// [`retry_on_intr`]. 321 /// 322 /// [`retry_on_intr`]: io::retry_on_intr 323 pub const INTR: Self = Self::from_errno(errno::EINTR); 324 /// `EINVAL` 325 pub const INVAL: Self = Self::from_errno(errno::EINVAL); 326 /// `EIO` 327 pub const IO: Self = Self::from_errno(errno::EIO); 328 /// `EISCONN` 329 pub const ISCONN: Self = Self::from_errno(errno::EISCONN); 330 /// `EISDIR` 331 pub const ISDIR: Self = Self::from_errno(errno::EISDIR); 332 /// `EISNAM` 333 pub const ISNAM: Self = Self::from_errno(errno::EISNAM); 334 /// `EKEYEXPIRED` 335 pub const KEYEXPIRED: Self = Self::from_errno(errno::EKEYEXPIRED); 336 /// `EKEYREJECTED` 337 pub const KEYREJECTED: Self = Self::from_errno(errno::EKEYREJECTED); 338 /// `EKEYREVOKED` 339 pub const KEYREVOKED: Self = Self::from_errno(errno::EKEYREVOKED); 340 /// `EL2HLT` 341 pub const L2HLT: Self = Self::from_errno(errno::EL2HLT); 342 /// `EL2NSYNC` 343 pub const L2NSYNC: Self = Self::from_errno(errno::EL2NSYNC); 344 /// `EL3HLT` 345 pub const L3HLT: Self = Self::from_errno(errno::EL3HLT); 346 /// `EL3RST` 347 pub const L3RST: Self = Self::from_errno(errno::EL3RST); 348 /// `ELIBACC` 349 pub const LIBACC: Self = Self::from_errno(errno::ELIBACC); 350 /// `ELIBBAD` 351 pub const LIBBAD: Self = Self::from_errno(errno::ELIBBAD); 352 /// `ELIBEXEC` 353 pub const LIBEXEC: Self = Self::from_errno(errno::ELIBEXEC); 354 /// `ELIBMAX` 355 pub const LIBMAX: Self = Self::from_errno(errno::ELIBMAX); 356 /// `ELIBSCN` 357 pub const LIBSCN: Self = Self::from_errno(errno::ELIBSCN); 358 /// `ELNRNG` 359 pub const LNRNG: Self = Self::from_errno(errno::ELNRNG); 360 /// `ELOOP` 361 pub const LOOP: Self = Self::from_errno(errno::ELOOP); 362 /// `EMEDIUMTYPE` 363 pub const MEDIUMTYPE: Self = Self::from_errno(errno::EMEDIUMTYPE); 364 /// `EMFILE` 365 pub const MFILE: Self = Self::from_errno(errno::EMFILE); 366 /// `EMLINK` 367 pub const MLINK: Self = Self::from_errno(errno::EMLINK); 368 /// `EMSGSIZE` 369 pub const MSGSIZE: Self = Self::from_errno(errno::EMSGSIZE); 370 /// `EMULTIHOP` 371 pub const MULTIHOP: Self = Self::from_errno(errno::EMULTIHOP); 372 /// `ENAMETOOLONG` 373 pub const NAMETOOLONG: Self = Self::from_errno(errno::ENAMETOOLONG); 374 /// `ENAVAIL` 375 pub const NAVAIL: Self = Self::from_errno(errno::ENAVAIL); 376 /// `ENETDOWN` 377 pub const NETDOWN: Self = Self::from_errno(errno::ENETDOWN); 378 /// `ENETRESET` 379 pub const NETRESET: Self = Self::from_errno(errno::ENETRESET); 380 /// `ENETUNREACH` 381 pub const NETUNREACH: Self = Self::from_errno(errno::ENETUNREACH); 382 /// `ENFILE` 383 pub const NFILE: Self = Self::from_errno(errno::ENFILE); 384 /// `ENOANO` 385 pub const NOANO: Self = Self::from_errno(errno::ENOANO); 386 /// `ENOBUFS` 387 pub const NOBUFS: Self = Self::from_errno(errno::ENOBUFS); 388 /// `ENOCSI` 389 pub const NOCSI: Self = Self::from_errno(errno::ENOCSI); 390 /// `ENODATA` 391 #[doc(alias = "NOATTR")] 392 pub const NODATA: Self = Self::from_errno(errno::ENODATA); 393 /// `ENODEV` 394 pub const NODEV: Self = Self::from_errno(errno::ENODEV); 395 /// `ENOENT` 396 pub const NOENT: Self = Self::from_errno(errno::ENOENT); 397 /// `ENOEXEC` 398 pub const NOEXEC: Self = Self::from_errno(errno::ENOEXEC); 399 /// `ENOKEY` 400 pub const NOKEY: Self = Self::from_errno(errno::ENOKEY); 401 /// `ENOLCK` 402 pub const NOLCK: Self = Self::from_errno(errno::ENOLCK); 403 /// `ENOLINK` 404 pub const NOLINK: Self = Self::from_errno(errno::ENOLINK); 405 /// `ENOMEDIUM` 406 pub const NOMEDIUM: Self = Self::from_errno(errno::ENOMEDIUM); 407 /// `ENOMEM` 408 pub const NOMEM: Self = Self::from_errno(errno::ENOMEM); 409 /// `ENOMSG` 410 pub const NOMSG: Self = Self::from_errno(errno::ENOMSG); 411 /// `ENONET` 412 pub const NONET: Self = Self::from_errno(errno::ENONET); 413 /// `ENOPKG` 414 pub const NOPKG: Self = Self::from_errno(errno::ENOPKG); 415 /// `ENOPROTOOPT` 416 pub const NOPROTOOPT: Self = Self::from_errno(errno::ENOPROTOOPT); 417 /// `ENOSPC` 418 pub const NOSPC: Self = Self::from_errno(errno::ENOSPC); 419 /// `ENOSR` 420 pub const NOSR: Self = Self::from_errno(errno::ENOSR); 421 /// `ENOSTR` 422 pub const NOSTR: Self = Self::from_errno(errno::ENOSTR); 423 /// `ENOSYS` 424 pub const NOSYS: Self = Self::from_errno(errno::ENOSYS); 425 /// `ENOTBLK` 426 pub const NOTBLK: Self = Self::from_errno(errno::ENOTBLK); 427 /// `ENOTCONN` 428 pub const NOTCONN: Self = Self::from_errno(errno::ENOTCONN); 429 /// `ENOTDIR` 430 pub const NOTDIR: Self = Self::from_errno(errno::ENOTDIR); 431 /// `ENOTEMPTY` 432 pub const NOTEMPTY: Self = Self::from_errno(errno::ENOTEMPTY); 433 /// `ENOTNAM` 434 pub const NOTNAM: Self = Self::from_errno(errno::ENOTNAM); 435 /// `ENOTRECOVERABLE` 436 pub const NOTRECOVERABLE: Self = Self::from_errno(errno::ENOTRECOVERABLE); 437 /// `ENOTSOCK` 438 pub const NOTSOCK: Self = Self::from_errno(errno::ENOTSOCK); 439 /// `ENOTSUP` 440 // On Linux, `ENOTSUP` has the same value as `EOPNOTSUPP`. 441 pub const NOTSUP: Self = Self::from_errno(errno::EOPNOTSUPP); 442 /// `ENOTTY` 443 pub const NOTTY: Self = Self::from_errno(errno::ENOTTY); 444 /// `ENOTUNIQ` 445 pub const NOTUNIQ: Self = Self::from_errno(errno::ENOTUNIQ); 446 /// `ENXIO` 447 pub const NXIO: Self = Self::from_errno(errno::ENXIO); 448 /// `EOPNOTSUPP` 449 pub const OPNOTSUPP: Self = Self::from_errno(errno::EOPNOTSUPP); 450 /// `EOVERFLOW` 451 pub const OVERFLOW: Self = Self::from_errno(errno::EOVERFLOW); 452 /// `EOWNERDEAD` 453 pub const OWNERDEAD: Self = Self::from_errno(errno::EOWNERDEAD); 454 /// `EPERM` 455 pub const PERM: Self = Self::from_errno(errno::EPERM); 456 /// `EPFNOSUPPORT` 457 pub const PFNOSUPPORT: Self = Self::from_errno(errno::EPFNOSUPPORT); 458 /// `EPIPE` 459 pub const PIPE: Self = Self::from_errno(errno::EPIPE); 460 /// `EPROTO` 461 pub const PROTO: Self = Self::from_errno(errno::EPROTO); 462 /// `EPROTONOSUPPORT` 463 pub const PROTONOSUPPORT: Self = Self::from_errno(errno::EPROTONOSUPPORT); 464 /// `EPROTOTYPE` 465 pub const PROTOTYPE: Self = Self::from_errno(errno::EPROTOTYPE); 466 /// `ERANGE` 467 pub const RANGE: Self = Self::from_errno(errno::ERANGE); 468 /// `EREMCHG` 469 pub const REMCHG: Self = Self::from_errno(errno::EREMCHG); 470 /// `EREMOTE` 471 pub const REMOTE: Self = Self::from_errno(errno::EREMOTE); 472 /// `EREMOTEIO` 473 pub const REMOTEIO: Self = Self::from_errno(errno::EREMOTEIO); 474 /// `ERESTART` 475 pub const RESTART: Self = Self::from_errno(errno::ERESTART); 476 /// `ERFKILL` 477 pub const RFKILL: Self = Self::from_errno(errno::ERFKILL); 478 /// `EROFS` 479 pub const ROFS: Self = Self::from_errno(errno::EROFS); 480 /// `ESHUTDOWN` 481 pub const SHUTDOWN: Self = Self::from_errno(errno::ESHUTDOWN); 482 /// `ESOCKTNOSUPPORT` 483 pub const SOCKTNOSUPPORT: Self = Self::from_errno(errno::ESOCKTNOSUPPORT); 484 /// `ESPIPE` 485 pub const SPIPE: Self = Self::from_errno(errno::ESPIPE); 486 /// `ESRCH` 487 pub const SRCH: Self = Self::from_errno(errno::ESRCH); 488 /// `ESRMNT` 489 pub const SRMNT: Self = Self::from_errno(errno::ESRMNT); 490 /// `ESTALE` 491 pub const STALE: Self = Self::from_errno(errno::ESTALE); 492 /// `ESTRPIPE` 493 pub const STRPIPE: Self = Self::from_errno(errno::ESTRPIPE); 494 /// `ETIME` 495 pub const TIME: Self = Self::from_errno(errno::ETIME); 496 /// `ETIMEDOUT` 497 pub const TIMEDOUT: Self = Self::from_errno(errno::ETIMEDOUT); 498 /// `E2BIG` 499 #[doc(alias = "2BIG")] 500 pub const TOOBIG: Self = Self::from_errno(errno::E2BIG); 501 /// `ETOOMANYREFS` 502 pub const TOOMANYREFS: Self = Self::from_errno(errno::ETOOMANYREFS); 503 /// `ETXTBSY` 504 pub const TXTBSY: Self = Self::from_errno(errno::ETXTBSY); 505 /// `EUCLEAN` 506 pub const UCLEAN: Self = Self::from_errno(errno::EUCLEAN); 507 /// `EUNATCH` 508 pub const UNATCH: Self = Self::from_errno(errno::EUNATCH); 509 /// `EUSERS` 510 pub const USERS: Self = Self::from_errno(errno::EUSERS); 511 /// `EWOULDBLOCK` 512 pub const WOULDBLOCK: Self = Self::from_errno(errno::EWOULDBLOCK); 513 /// `EXDEV` 514 pub const XDEV: Self = Self::from_errno(errno::EXDEV); 515 /// `EXFULL` 516 pub const XFULL: Self = Self::from_errno(errno::EXFULL); 517 } 518