diff --git a/library/std/build.rs b/library/std/build.rs index 164bca7c43665..49354d5a58cba 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -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") diff --git a/library/std/src/os/aix/fs.rs b/library/std/src/os/aix/fs.rs new file mode 100644 index 0000000000000..ac9dd45f05426 --- /dev/null +++ b/library/std/src/os/aix/fs.rs @@ -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 + } +} diff --git a/library/std/src/os/aix/mod.rs b/library/std/src/os/aix/mod.rs new file mode 100644 index 0000000000000..7f86a3c77f210 --- /dev/null +++ b/library/std/src/os/aix/mod.rs @@ -0,0 +1,6 @@ +//! AIX specific definitions. + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub mod raw; diff --git a/library/std/src/os/aix/raw.rs b/library/std/src/os/aix/raw.rs new file mode 100644 index 0000000000000..b4c8dc72cfe5b --- /dev/null +++ b/library/std/src/os/aix/raw.rs @@ -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}; diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 11ad21515fdec..6e11b92b618a3 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -97,6 +97,8 @@ pub mod wasi; pub mod windows; // Others. +#[cfg(target_os = "aix")] +pub mod aix; #[cfg(target_os = "android")] pub mod android; #[cfg(target_os = "dragonfly")] diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 3724e90afbd16..5ba8719e6ffeb 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -37,6 +37,8 @@ use crate::os::linux as platform; #[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")] diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index 19334e2aff29c..2da17fabcd64d 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -70,6 +70,7 @@ impl DoubleEndedIterator for Args { target_os = "redox", target_os = "vxworks", target_os = "horizon", + target_os = "aix", target_os = "nto", target_os = "hurd", ))] diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index c6d8578a62986..3bb492fa98bcf 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -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 = ""; +} diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 5ed2bdd7fe32b..e1c58f2ba3c37 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -54,6 +54,7 @@ use libc::fstatat64; target_os = "fuchsia", target_os = "redox", target_os = "illumos", + target_os = "aix", target_os = "nto", target_os = "vita", ))] @@ -71,6 +72,7 @@ use libc::readdir64_r; 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 @@ impl FileAttr { } } -#[cfg(not(any(target_os = "netbsd", target_os = "nto")))] +#[cfg(target_os = "aix")] +impl FileAttr { + pub fn modified(&self) -> io::Result { + 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 { + 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 { + 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 @@ impl Iterator for ReadDir { #[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 @@ 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", @@ -874,6 +898,7 @@ impl DirEntry { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", target_os = "nto", target_os = "vita", ))] @@ -886,6 +911,7 @@ impl DirEntry { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", target_os = "nto", target_os = "vita", )))] @@ -920,6 +946,7 @@ impl DirEntry { target_os = "espidf", target_os = "horizon", target_os = "vita", + target_os = "aix", target_os = "nto", target_os = "hurd", ))] @@ -977,6 +1004,7 @@ impl DirEntry { 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 @@ impl DirEntry { 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 @@ mod remove_dir_impl { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", ))] fn is_dir(_ent: &DirEntry) -> Option { None @@ -2036,6 +2066,7 @@ mod remove_dir_impl { target_os = "illumos", target_os = "haiku", target_os = "vxworks", + target_os = "aix", )))] fn is_dir(ent: &DirEntry) -> Option { match ent.entry.d_type { diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 3edafde71e937..01d8217342ce4 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -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, diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 01ff375d21517..dc3c037c0cb78 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -74,6 +74,7 @@ extern "C" { 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 @@ impl StdError for JoinPathsError { } } +#[cfg(target_os = "aix")] +pub fn current_exe() -> io::Result { + 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 { unsafe { diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 311ed95022f8c..e667f34aece05 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -218,6 +218,7 @@ impl Thread { 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 { target_os = "macos", target_os = "solaris", target_os = "illumos", + target_os = "aix", ))] { #[allow(unused_assignments)] #[allow(unused_mut)] diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index 4a732a2cabd26..a0117e1d165ca 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -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; diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index df4f286a526bd..94a91dd357c9f 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -145,6 +145,10 @@ extern "C" {} #[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" {}