d-major 0.0.0

Traverse directory trees in parallel, using relative entries to minimize allocation and maximize parallelism.
Documentation
/*
 * Description: Interact with the global errno variable.
 * This code is largely copied from the rust compiler's sys/pal/unix/os.rs: https://github.com/cosmicexplorer/rust/blob/cbfdf0b014cb04982a9cbeec1578001001167f6e/library/std/src/sys/pal/unix/os.rs.
 * The rust compiler is distributed under both the MIT and Apache v2 licenses.
 *
 * Copyright (C) 2025 d@nny mc² <dmc2@hypnicjerk.ai>
 * SPDX-License-Identifier: LGPL-3.0-or-later
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

//! Interact with the global errno variable.
//!
//! This code is largely copied from the rust compiler's [`sys/pal/unix/os.rs`](https://github.com/cosmicexplorer/rust/blob/cbfdf0b014cb04982a9cbeec1578001001167f6e/library/std/src/sys/pal/unix/os.rs).


pub type ErrnoLocation = libc::c_int;


cfg_if::cfg_if! {
  if #[cfg(feature = "nightly")] {
    pub type Errno = std::io::RawOsError;
  } else {
    pub type Errno = i32;
  }
}


unsafe extern "C" {
  #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
  #[cfg_attr(
    any(
      target_os = "linux",
      target_os = "emscripten",
      target_os = "fuchsia",
      target_os = "l4re",
      target_os = "hurd",
    ),
    link_name = "__errno_location"
  )]
  #[cfg_attr(
    any(
      target_os = "netbsd",
      target_os = "openbsd",
      target_os = "android",
      target_os = "redox",
      target_os = "nuttx",
      target_env = "newlib"
    ),
    link_name = "__errno"
  )]
  #[cfg_attr(
    any(target_os = "solaris", target_os = "illumos"),
    link_name = "___errno"
  )]
  #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
  #[cfg_attr(
    any(target_os = "freebsd", target_vendor = "apple"),
    link_name = "__error"
  )]
  #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
  #[cfg_attr(target_os = "aix", link_name = "_Errno")]
  fn errno_location() -> *mut ErrnoLocation;
}

/// Returns the platform-specific value of errno
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
pub fn errno() -> Errno { unsafe { (*errno_location()) as Errno } }

/// Sets the platform-specific value of errno
// needed for readdir and syscall!
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
#[allow(dead_code)] // but not all target cfgs actually end up using it
pub fn set_errno(e: Errno) { unsafe { *errno_location() = e as ErrnoLocation } }

#[cfg(target_os = "vxworks")]
pub fn errno() -> Errno { unsafe { libc::errnoGet() } }

#[cfg(target_os = "rtems")]
pub fn errno() -> Errno {
  unsafe extern "C" {
    #[thread_local]
    static _tls_errno: ErrnoLocation;
  }

  unsafe { _tls_errno as Errno }
}

#[cfg(target_os = "dragonfly")]
pub fn errno() -> Errno {
  unsafe extern "C" {
    #[thread_local]
    static errno: ErrnoLocation;
  }

  unsafe { errno as Errno }
}

#[cfg(target_os = "dragonfly")]
#[allow(dead_code)]
pub fn set_errno(e: Errno) {
  unsafe extern "C" {
    #[thread_local]
    static mut errno: ErrnoLocation;
  }

  unsafe {
    errno = e;
  }
}


pub const UNSET_ERRNO: Errno = 0;


#[inline]
pub fn errno_is_unset() -> bool { errno() == UNSET_ERRNO }


#[inline]
pub fn maybe_errno(errno: Errno) -> Option<std::io::Error> {
  debug_assert!(errno >= 0);
  if errno == UNSET_ERRNO {
    return None;
  }
  let err = std::io::Error::from_raw_os_error(errno);
  Some(err)
}

#[inline]
pub fn with_cleared_errno<T>(f: impl FnOnce() -> T) -> Result<T, std::io::Error> {
  set_errno(UNSET_ERRNO);
  let ret = f();
  if let Some(err) = maybe_errno(errno()) {
    return Err(err);
  }
  Ok(ret)
}