Support AIX in Rust standard library

This commit is contained in:
Qiu Chaofan 2023-04-03 12:33:51 +08:00
parent 1f48cbc3f8
commit 14d29be03c
14 changed files with 462 additions and 3 deletions

View file

@ -42,6 +42,7 @@ fn main() {
|| target.contains("solid")
|| target.contains("nintendo-3ds")
|| target.contains("vita")
|| target.contains("aix")
|| target.contains("nto")
|| target.contains("xous")
|| target.contains("hurd")

View file

@ -0,0 +1,348 @@
//! AIX specific extensions to primitives in the [`std::fs`] module.
//!
//! [`std::fs`]: crate::fs
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Returns the device ID on which this file resides.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_dev());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_dev(&self) -> u64;
/// Returns the inode number.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ino());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ino(&self) -> u64;
/// Returns the file type and mode.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mode());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mode(&self) -> u32;
/// Returns the number of hard links to file.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_nlink());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_nlink(&self) -> u64;
/// Returns the user ID of the file owner.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_uid());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_uid(&self) -> u32;
/// Returns the group ID of the file owner.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_gid());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_gid(&self) -> u32;
/// Returns the device ID that this file represents. Only relevant for special file.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_rdev());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_rdev(&self) -> u64;
/// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
///
/// The size of a symbolic link is the length of the pathname it contains,
/// without a terminating null byte.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_size());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_size(&self) -> u64;
/// Returns the last access time of the file, in seconds since Unix Epoch.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_atime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime(&self) -> i64;
/// Returns the last access time of the file, in nanoseconds since [`st_atime`].
///
/// [`st_atime`]: Self::st_atime
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_atime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime_nsec(&self) -> i64;
/// Returns the last modification time of the file, in seconds since Unix Epoch.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mtime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime(&self) -> i64;
/// Returns the last modification time of the file, in nanoseconds since [`st_mtime`].
///
/// [`st_mtime`]: Self::st_mtime
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mtime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime_nsec(&self) -> i64;
/// Returns the last status change time of the file, in seconds since Unix Epoch.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ctime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime(&self) -> i64;
/// Returns the last status change time of the file, in nanoseconds since [`st_ctime`].
///
/// [`st_ctime`]: Self::st_ctime
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ctime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime_nsec(&self) -> i64;
/// Returns the "preferred" block size for efficient filesystem I/O.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_blksize());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blksize(&self) -> u64;
/// Returns the number of blocks allocated to the file, 512-byte units.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::aix::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_blocks());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blocks(&self) -> u64;
}
#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
fn st_dev(&self) -> u64 {
self.as_inner().as_inner().st_dev as u64
}
fn st_ino(&self) -> u64 {
self.as_inner().as_inner().st_ino as u64
}
fn st_mode(&self) -> u32 {
self.as_inner().as_inner().st_mode as u32
}
fn st_nlink(&self) -> u64 {
self.as_inner().as_inner().st_nlink as u64
}
fn st_uid(&self) -> u32 {
self.as_inner().as_inner().st_uid as u32
}
fn st_gid(&self) -> u32 {
self.as_inner().as_inner().st_gid as u32
}
fn st_rdev(&self) -> u64 {
self.as_inner().as_inner().st_rdev as u64
}
fn st_size(&self) -> u64 {
self.as_inner().as_inner().st_size as u64
}
fn st_atime(&self) -> i64 {
self.as_inner().as_inner().st_atime.tv_sec as i64
}
fn st_atime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_atime.tv_nsec as i64
}
fn st_mtime(&self) -> i64 {
self.as_inner().as_inner().st_mtime.tv_sec as i64
}
fn st_mtime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_mtime.tv_nsec as i64
}
fn st_ctime(&self) -> i64 {
self.as_inner().as_inner().st_ctime.tv_sec as i64
}
fn st_ctime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_ctime.tv_nsec as i64
}
fn st_blksize(&self) -> u64 {
self.as_inner().as_inner().st_blksize as u64
}
fn st_blocks(&self) -> u64 {
self.as_inner().as_inner().st_blocks as u64
}
}

View file

@ -0,0 +1,6 @@
//! AIX specific definitions.
#![stable(feature = "raw_ext", since = "1.1.0")]
pub mod fs;
pub mod raw;

View file

@ -0,0 +1,9 @@
//! AIX specific raw type definitions.
#![stable(feature = "raw_ext", since = "1.1.0")]
#[stable(feature = "pthread_t", since = "1.8.0")]
pub use libc::pthread_t;
#[stable(feature = "raw_ext", since = "1.1.0")]
pub use libc::{blkcnt_t, blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t, stat, time_t};

View file

@ -97,6 +97,8 @@ pub mod windows {}
pub mod windows;
// Others.
#[cfg(target_os = "aix")]
pub mod aix;
#[cfg(target_os = "android")]
pub mod android;
#[cfg(target_os = "dragonfly")]

View file

@ -37,6 +37,8 @@
#[cfg(not(doc))]
mod platform {
#[cfg(target_os = "aix")]
pub use crate::os::aix::*;
#[cfg(target_os = "android")]
pub use crate::os::android::*;
#[cfg(target_os = "dragonfly")]

View file

@ -70,6 +70,7 @@ fn next_back(&mut self) -> Option<OsString> {
target_os = "redox",
target_os = "vxworks",
target_os = "horizon",
target_os = "aix",
target_os = "nto",
target_os = "hurd",
))]

View file

@ -261,3 +261,14 @@ pub mod os {
pub const EXE_SUFFIX: &str = "";
pub const EXE_EXTENSION: &str = "";
}
#[cfg(target_os = "aix")]
pub mod os {
pub const FAMILY: &str = "unix";
pub const OS: &str = "aix";
pub const DLL_PREFIX: &str = "lib";
pub const DLL_SUFFIX: &str = ".a";
pub const DLL_EXTENSION: &str = "a";
pub const EXE_SUFFIX: &str = "";
pub const EXE_EXTENSION: &str = "";
}

View file

@ -54,6 +54,7 @@
target_os = "fuchsia",
target_os = "redox",
target_os = "illumos",
target_os = "aix",
target_os = "nto",
target_os = "vita",
))]
@ -71,6 +72,7 @@
target_os = "l4re",
target_os = "fuchsia",
target_os = "redox",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -288,6 +290,7 @@ unsafe impl Sync for Dir {}
target_os = "illumos",
target_os = "fuchsia",
target_os = "redox",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -311,6 +314,7 @@ pub struct DirEntry {
target_os = "illumos",
target_os = "fuchsia",
target_os = "redox",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -320,8 +324,9 @@ struct dirent64_min {
#[cfg(not(any(
target_os = "solaris",
target_os = "illumos",
target_os = "aix",
target_os = "nto",
target_os = "vita"
target_os = "vita",
)))]
d_type: u8,
}
@ -333,6 +338,7 @@ struct dirent64_min {
target_os = "illumos",
target_os = "fuchsia",
target_os = "redox",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -464,7 +470,22 @@ pub fn created(&self) -> io::Result<SystemTime> {
}
}
#[cfg(not(any(target_os = "netbsd", target_os = "nto")))]
#[cfg(target_os = "aix")]
impl FileAttr {
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_mtime.tv_sec as i64, self.stat.st_mtime.tv_nsec as i64))
}
pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_atime.tv_sec as i64, self.stat.st_atime.tv_nsec as i64))
}
pub fn created(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(self.stat.st_ctime.tv_sec as i64, self.stat.st_ctime.tv_nsec as i64))
}
}
#[cfg(not(any(target_os = "netbsd", target_os = "nto", target_os = "aix")))]
impl FileAttr {
#[cfg(not(any(
target_os = "vxworks",
@ -671,6 +692,7 @@ impl Iterator for ReadDir {
target_os = "fuchsia",
target_os = "redox",
target_os = "illumos",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -748,6 +770,7 @@ macro_rules! offset_ptr {
#[cfg(not(any(
target_os = "solaris",
target_os = "illumos",
target_os = "aix",
target_os = "nto",
)))]
d_type: *offset_ptr!(entry_ptr, d_type) as u8,
@ -772,6 +795,7 @@ macro_rules! offset_ptr {
target_os = "fuchsia",
target_os = "redox",
target_os = "illumos",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -874,6 +898,7 @@ pub fn metadata(&self) -> io::Result<FileAttr> {
target_os = "illumos",
target_os = "haiku",
target_os = "vxworks",
target_os = "aix",
target_os = "nto",
target_os = "vita",
))]
@ -886,6 +911,7 @@ pub fn file_type(&self) -> io::Result<FileType> {
target_os = "illumos",
target_os = "haiku",
target_os = "vxworks",
target_os = "aix",
target_os = "nto",
target_os = "vita",
)))]
@ -920,6 +946,7 @@ pub fn file_type(&self) -> io::Result<FileType> {
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "aix",
target_os = "nto",
target_os = "hurd",
))]
@ -977,6 +1004,7 @@ fn name_bytes(&self) -> &[u8] {
target_os = "illumos",
target_os = "fuchsia",
target_os = "redox",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -991,6 +1019,7 @@ fn name_cstr(&self) -> &CStr {
target_os = "illumos",
target_os = "fuchsia",
target_os = "redox",
target_os = "aix",
target_os = "nto",
target_os = "vita",
target_os = "hurd",
@ -2026,6 +2055,7 @@ fn fdreaddir(dir_fd: OwnedFd) -> io::Result<(ReadDir, RawFd)> {
target_os = "illumos",
target_os = "haiku",
target_os = "vxworks",
target_os = "aix",
))]
fn is_dir(_ent: &DirEntry) -> Option<bool> {
None
@ -2036,6 +2066,7 @@ fn is_dir(_ent: &DirEntry) -> Option<bool> {
target_os = "illumos",
target_os = "haiku",
target_os = "vxworks",
target_os = "aix",
)))]
fn is_dir(ent: &DirEntry) -> Option<bool> {
match ent.entry.d_type {

View file

@ -278,6 +278,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
libc::ENOTDIR => NotADirectory,
#[cfg(not(target_os = "aix"))]
libc::ENOTEMPTY => DirectoryNotEmpty,
libc::EPIPE => BrokenPipe,
libc::EROFS => ReadOnlyFilesystem,

View file

@ -74,6 +74,7 @@
link_name = "__error"
)]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
#[cfg_attr(target_os = "aix", link_name = "_Errno")]
fn errno_location() -> *mut c_int;
}
@ -254,6 +255,41 @@ fn description(&self) -> &str {
}
}
#[cfg(target_os = "aix")]
pub fn current_exe() -> io::Result<PathBuf> {
use crate::io::ErrorKind;
#[cfg(test)]
use realstd::env;
#[cfg(not(test))]
use crate::env;
let exe_path = env::args().next().ok_or(io::const_io_error!(
ErrorKind::NotFound,
"an executable path was not found because no arguments were provided through argv"
))?;
let path = PathBuf::from(exe_path);
if path.is_absolute() {
return path.canonicalize();
}
// Search PWD to infer current_exe.
if let Some(pstr) = path.to_str() && pstr.contains("/") {
return getcwd().map(|cwd| cwd.join(path))?.canonicalize();
}
// Search PATH to infer current_exe.
if let Some(p) = getenv(OsStr::from_bytes("PATH".as_bytes())) {
for search_path in split_paths(&p) {
let pb = search_path.join(&path);
if pb.is_file() && let Ok(metadata) = crate::fs::metadata(&pb) &&
metadata.permissions().mode() & 0o111 != 0 {
return pb.canonicalize();
}
}
}
Err(io::const_io_error!(ErrorKind::NotFound, "an executable path was not found"))
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
pub fn current_exe() -> io::Result<PathBuf> {
unsafe {

View file

@ -218,6 +218,7 @@ pub fn set_name(name: &CStr) {
target_os = "redox",
target_os = "vxworks",
target_os = "hurd",
target_os = "aix",
))]
pub fn set_name(_name: &CStr) {
// Newlib, Emscripten, and VxWorks have no way to set a thread name.
@ -317,6 +318,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
target_os = "macos",
target_os = "solaris",
target_os = "illumos",
target_os = "aix",
))] {
#[allow(unused_assignments)]
#[allow(unused_mut)]

View file

@ -102,7 +102,12 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
}
}
#[cfg(any(target_os = "vxworks", target_os = "horizon", target_os = "emscripten"))]
#[cfg(any(
target_os = "vxworks",
target_os = "horizon",
target_os = "emscripten",
target_os = "aix"
))]
#[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten)
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
use crate::sys_common::thread_local_dtor::register_dtor_fallback;

View file

@ -145,6 +145,10 @@
#[link(name = "gcc_s")]
extern "C" {}
#[cfg(target_os = "aix")]
#[link(name = "unwind")]
extern "C" {}
#[cfg(target_os = "nto")]
#[link(name = "gcc_s")]
extern "C" {}