root: PathBuf,
}
-#[derive(Clone)]
pub struct ReadDir {
inner: Arc<InnerReadDir>,
+ #[cfg(not(any(
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "fuchsia",
+ target_os = "redox",
+ )))]
end_of_stream: bool,
}
pub struct DirEntry {
entry: dirent64,
- dir: ReadDir,
+ dir: Arc<InnerReadDir>,
// We need to store an owned copy of the entry name
// on Solaris and Fuchsia because a) it uses a zero-length
// array to store the name, b) its lifetime between readdir
#[cfg(not(target_os = "netbsd"))]
impl FileAttr {
+ #[cfg(not(target_os = "vxworks"))]
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
tv_sec: self.stat.st_mtime as libc::time_t,
}))
}
+ #[cfg(target_os = "vxworks")]
+ pub fn modified(&self) -> io::Result<SystemTime> {
+ Ok(SystemTime::from(libc::timespec {
+ tv_sec: self.stat.st_mtime as libc::time_t,
+ tv_nsec: 0,
+ }))
+ }
+
+ #[cfg(not(target_os = "vxworks"))]
pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
tv_sec: self.stat.st_atime as libc::time_t,
}))
}
+ #[cfg(target_os = "vxworks")]
+ pub fn accessed(&self) -> io::Result<SystemTime> {
+ Ok(SystemTime::from(libc::timespec {
+ tv_sec: self.stat.st_atime as libc::time_t,
+ tv_nsec: 0,
+ }))
+ }
+
#[cfg(any(
target_os = "freebsd",
target_os = "openbsd",
name: slice::from_raw_parts(name as *const u8, namelen as usize)
.to_owned()
.into_boxed_slice(),
- dir: self.clone(),
+ dir: Arc::clone(&self.inner),
};
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
return Some(Ok(ret));
}
unsafe {
- let mut ret = DirEntry { entry: mem::zeroed(), dir: self.clone() };
+ let mut ret = DirEntry { entry: mem::zeroed(), dir: Arc::clone(&self.inner) };
let mut entry_ptr = ptr::null_mut();
loop {
if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
impl DirEntry {
pub fn path(&self) -> PathBuf {
- self.dir.inner.root.join(OsStr::from_bytes(self.name_bytes()))
+ self.dir.root.join(OsStr::from_bytes(self.name_bytes()))
}
pub fn file_name(&self) -> OsString {
#[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
pub fn metadata(&self) -> io::Result<FileAttr> {
- let fd = cvt(unsafe { dirfd(self.dir.inner.dirp.0) })?;
+ let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?;
let name = self.entry.d_name.as_ptr();
cfg_has_statx! {
lstat(&self.path())
}
- #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "haiku"))]
+ #[cfg(any(
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "haiku",
+ target_os = "vxworks"
+ ))]
pub fn file_type(&self) -> io::Result<FileType> {
lstat(&self.path()).map(|m| m.file_type())
}
- #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "haiku")))]
+ #[cfg(not(any(
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "haiku",
+ target_os = "vxworks"
+ )))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
target_os = "haiku",
target_os = "l4re",
target_os = "fuchsia",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "vxworks"
))]
pub fn ino(&self) -> u64 {
self.entry.d_ino as u64
target_os = "linux",
target_os = "emscripten",
target_os = "l4re",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "vxworks"
))]
fn name_bytes(&self) -> &[u8] {
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() }
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fcntl(fd, libc::F_FULLFSYNC)
}
- #[cfg(target_os = "linux")]
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "android",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ ))]
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fdatasync(fd)
}
- #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "linux")))]
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )))]
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fsync(fd)
}
Some(PathBuf::from(OsString::from_vec(buf)))
}
- #[cfg(not(any(target_os = "linux", target_os = "macos")))]
+ #[cfg(target_os = "vxworks")]
+ fn get_path(fd: c_int) -> Option<PathBuf> {
+ let mut buf = vec![0; libc::PATH_MAX as usize];
+ let n = unsafe { libc::ioctl(fd, libc::FIOGETNAME, buf.as_ptr()) };
+ if n == -1 {
+ return None;
+ }
+ let l = buf.iter().position(|&c| c == 0).unwrap();
+ buf.truncate(l as usize);
+ Some(PathBuf::from(OsString::from_vec(buf)))
+ }
+
+ #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "vxworks")))]
fn get_path(_fd: c_int) -> Option<PathBuf> {
// FIXME(#24570): implement this for other Unix platforms
None
}
- #[cfg(any(target_os = "linux", target_os = "macos"))]
+ #[cfg(any(target_os = "linux", target_os = "macos", target_os = "vxworks"))]
fn get_mode(fd: c_int) -> Option<(bool, bool)> {
let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
if mode == -1 {
}
}
- #[cfg(not(any(target_os = "linux", target_os = "macos")))]
+ #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "vxworks")))]
fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
// FIXME(#24570): implement this for other Unix platforms
None
Err(Error::last_os_error())
} else {
let inner = InnerReadDir { dirp: Dir(ptr), root };
- Ok(ReadDir { inner: Arc::new(inner), end_of_stream: false })
+ Ok(ReadDir {
+ inner: Arc::new(inner),
+ #[cfg(not(any(
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "fuchsia",
+ target_os = "redox",
+ )))]
+ end_of_stream: false,
+ })
}
}
}
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
let src = cstr(src)?;
let dst = cstr(dst)?;
- cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?;
+ cfg_if::cfg_if! {
+ if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] {
+ // VxWorks, Redox, and old versions of Android lack `linkat`, so use
+ // `link` instead. POSIX leaves it implementation-defined whether
+ // `link` follows symlinks, so rely on the `symlink_hard_link` test
+ // in library/std/src/fs/tests.rs to check the behavior.
+ cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?;
+ } else {
+ // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives
+ // us a flag to specify how symlinks should be handled. Pass 0 as
+ // the flags argument, meaning don't follow symlinks.
+ cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?;
+ }
+ }
Ok(())
}