aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sys/unix/fs.rs
diff options
context:
space:
mode:
authorFenrir <[email protected]>2018-01-21 14:06:28 -0700
committerFenrirWolf <[email protected]>2018-01-21 19:16:33 -0700
commit23be3f4885688e5e0011005e2295c75168854c0a (patch)
treedd0850f9c73c489e114a761d5c0757f3dbec3a65 /ctr-std/src/sys/unix/fs.rs
parentUpdate CI for Rust nightly-2017-12-01 + other fixes (diff)
downloadctru-rs-23be3f4885688e5e0011005e2295c75168854c0a.tar.xz
ctru-rs-23be3f4885688e5e0011005e2295c75168854c0a.zip
Recreate ctr-std from latest nightly
Diffstat (limited to 'ctr-std/src/sys/unix/fs.rs')
-rw-r--r--ctr-std/src/sys/unix/fs.rs131
1 files changed, 114 insertions, 17 deletions
diff --git a/ctr-std/src/sys/unix/fs.rs b/ctr-std/src/sys/unix/fs.rs
index 06413c3..f30b270 100644
--- a/ctr-std/src/sys/unix/fs.rs
+++ b/ctr-std/src/sys/unix/fs.rs
@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![allow(dead_code)]
+
use os::unix::prelude::*;
use ffi::{CString, CStr, OsString, OsStr};
@@ -23,8 +25,8 @@ use sys::time::SystemTime;
use sys::{cvt, cvt_r};
use sys_common::{AsInner, FromInner};
-use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, lseek as lseek64,
- dirent as dirent64, open as open64, ftruncate as ftruncate64, off_t as off64_t};
+use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
+ ftruncate as ftruncate64, lseek as lseek64, dirent as dirent64, open as open64};
use libc::{readdir_r as readdir64_r};
pub struct File(FileDesc);
@@ -47,6 +49,12 @@ unsafe impl Sync for Dir {}
pub struct DirEntry {
entry: dirent64,
root: Arc<PathBuf>,
+ // We need to store an owned copy of the directory name
+ // on Solaris and Fuchsia because a) it uses a zero-length
+ // array to store the name, b) its lifetime between readdir
+ // calls is not guaranteed.
+ #[cfg(any(target_os = "solaris", target_os = "fuchsia"))]
+ name: Box<[u8]>
}
#[derive(Clone, Debug)]
@@ -75,7 +83,7 @@ pub struct DirBuilder { mode: mode_t }
impl FileAttr {
pub fn size(&self) -> u64 { self.stat.st_size as u64 }
pub fn perm(&self) -> FilePermissions {
- FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 }
+ FilePermissions { mode: (self.stat.st_mode as mode_t) }
}
pub fn file_type(&self) -> FileType {
@@ -85,17 +93,15 @@ impl FileAttr {
impl FileAttr {
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,
- }))
+ Err(io::Error::new(io::ErrorKind::Other,
+ "modification time is not available on this platform \
+ currently"))
}
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,
- }))
+ Err(io::Error::new(io::ErrorKind::Other,
+ "access time is not available on this platform \
+ currently"))
}
pub fn created(&self) -> io::Result<SystemTime> {
@@ -110,11 +116,17 @@ impl AsInner<stat64> for FileAttr {
}
impl FilePermissions {
- pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
+ pub fn readonly(&self) -> bool {
+ // check if any class (owner, group, others) has write permission
+ self.mode & 0o222 == 0
+ }
+
pub fn set_readonly(&mut self, readonly: bool) {
if readonly {
+ // remove write permission for all classes; equivalent to `chmod a-w <file>`
self.mode &= !0o222;
} else {
+ // add write permission for all classes; equivalent to `chmod a+w <file>`
self.mode |= 0o222;
}
}
@@ -146,6 +158,42 @@ impl fmt::Debug for ReadDir {
impl Iterator for ReadDir {
type Item = io::Result<DirEntry>;
+ #[cfg(any(target_os = "solaris", target_os = "fuchsia"))]
+ fn next(&mut self) -> Option<io::Result<DirEntry>> {
+ unsafe {
+ loop {
+ // Although readdir_r(3) would be a correct function to use here because
+ // of the thread safety, on Illumos and Fuchsia the readdir(3C) function
+ // is safe to use in threaded applications and it is generally preferred
+ // over the readdir_r(3C) function.
+ super::os::set_errno(0);
+ let entry_ptr = libc::readdir(self.dirp.0);
+ if entry_ptr.is_null() {
+ // NULL can mean either the end is reached or an error occurred.
+ // So we had to clear errno beforehand to check for an error now.
+ return match super::os::errno() {
+ 0 => None,
+ e => Some(Err(Error::from_raw_os_error(e))),
+ }
+ }
+
+ let name = (*entry_ptr).d_name.as_ptr();
+ let namelen = libc::strlen(name) as usize;
+
+ let ret = DirEntry {
+ entry: *entry_ptr,
+ name: ::slice::from_raw_parts(name as *const u8,
+ namelen as usize).to_owned().into_boxed_slice(),
+ root: self.root.clone()
+ };
+ if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
+ return Some(Ok(ret))
+ }
+ }
+ }
+ }
+
+ #[cfg(not(any(target_os = "solaris", target_os = "fuchsia")))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
unsafe {
let mut ret = DirEntry {
@@ -188,6 +236,12 @@ impl DirEntry {
lstat(&self.path())
}
+ #[cfg(any(target_os = "solaris", target_os = "haiku"))]
+ pub fn file_type(&self) -> io::Result<FileType> {
+ lstat(&self.path()).map(|m| m.file_type())
+ }
+
+ #[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@@ -293,7 +347,7 @@ impl File {
// Linux kernel then the flag is just ignored by the OS, so we continue
// to explicitly ask for a CLOEXEC fd here.
//
- // The CLOEXEC flag, however, is supported on versions of OSX/BSD/etc
+ // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc
// that we support, so we only do this on Linux currently.
if cfg!(target_os = "linux") {
fd.set_cloexec()?;
@@ -323,6 +377,10 @@ impl File {
}
pub fn truncate(&self, size: u64) -> io::Result<()> {
+ #[cfg(target_os = "android")]
+ return ::sys::android::ftruncate64(self.0.raw(), size);
+
+ #[cfg(not(target_os = "android"))]
return cvt_r(|| unsafe {
ftruncate64(self.0.raw(), size as off64_t)
}).map(|_| ());
@@ -332,10 +390,6 @@ impl File {
self.0.read(buf)
}
- pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
- self.0.read_to_end(buf)
- }
-
pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.0.read_at(buf, offset)
}
@@ -358,6 +412,8 @@ impl File {
SeekFrom::End(off) => (libc::SEEK_END, off),
SeekFrom::Current(off) => (libc::SEEK_CUR, off),
};
+ #[cfg(target_os = "emscripten")]
+ let pos = pos as i32;
let n = cvt(unsafe { lseek64(self.0.raw(), pos, whence) })?;
Ok(n as u64)
}
@@ -404,11 +460,52 @@ impl FromInner<c_int> for File {
impl fmt::Debug for File {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ #[cfg(target_os = "linux")]
+ fn get_path(fd: c_int) -> Option<PathBuf> {
+ let mut p = PathBuf::from("/proc/self/fd");
+ p.push(&fd.to_string());
+ readlink(&p).ok()
+ }
+
+ #[cfg(target_os = "macos")]
+ fn get_path(fd: c_int) -> Option<PathBuf> {
+ // FIXME: The use of PATH_MAX is generally not encouraged, but it
+ // is inevitable in this case because macOS defines `fcntl` with
+ // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
+ // alternatives. If a better method is invented, it should be used
+ // instead.
+ let mut buf = vec![0;libc::PATH_MAX as usize];
+ let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) };
+ if n == -1 {
+ return None;
+ }
+ let l = buf.iter().position(|&c| c == 0).unwrap();
+ buf.truncate(l as usize);
+ buf.shrink_to_fit();
+ Some(PathBuf::from(OsString::from_vec(buf)))
+ }
+
+ #[cfg(not(any(target_os = "linux", target_os = "macos")))]
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"))]
+ fn get_mode(fd: c_int) -> Option<(bool, bool)> {
+ let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
+ if mode == -1 {
+ return None;
+ }
+ match mode & libc::O_ACCMODE {
+ libc::O_RDONLY => Some((true, false)),
+ libc::O_RDWR => Some((true, true)),
+ libc::O_WRONLY => Some((false, true)),
+ _ => None
+ }
+ }
+
+ #[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
// FIXME(#24570): implement this for other Unix platforms
None