about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorChris Wong <lambda.fairy@gmail.com>2015-04-19 21:27:19 +1200
committerChris Wong <lambda.fairy@gmail.com>2015-04-21 17:13:36 +1200
commit1131bc0a0f9d4ce920f239dccbd0fcfe1c940548 (patch)
treeb020e8d15fa077748f031c429886d95415ac7a14 /src
parent21c48c3e823ed21266e96779d700946db957a965 (diff)
downloadrust-1131bc0a0f9d4ce920f239dccbd0fcfe1c940548.tar.gz
rust-1131bc0a0f9d4ce920f239dccbd0fcfe1c940548.zip
Implement Debug for File
This patch adds a `Debug` impl for `std::fs::File`.

On all platforms (Unix and Windows) it shows the file descriptor.

On Linux, it displays the path and access mode as well.

Ideally we should show the path/mode for all platforms, not just Linux,
but this will do for now.

cc #24570
Diffstat (limited to 'src')
-rw-r--r--src/liblibc/lib.rs2
-rw-r--r--src/libstd/fs.rs7
-rw-r--r--src/libstd/sys/unix/fs2.rs49
-rw-r--r--src/libstd/sys/windows/fs2.rs10
4 files changed, 68 insertions, 0 deletions
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index f7e92d61474..24a4a457224 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -3296,6 +3296,8 @@ pub mod consts {
             pub const F_GETFL : c_int = 3;
             pub const F_SETFL : c_int = 4;
 
+            pub const O_ACCMODE : c_int = 3;
+
             pub const SIGTRAP : c_int = 5;
             pub const SIG_IGN: size_t = 1;
 
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 8af3311c426..e8cdee9aca4 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -19,6 +19,7 @@
 
 use core::prelude::*;
 
+use fmt;
 use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
 use path::{Path, PathBuf};
 use sys::fs2 as fs_imp;
@@ -305,6 +306,12 @@ impl FromInner<fs_imp::File> for File {
     }
 }
 
+impl fmt::Debug for File {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.inner.fmt(f)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Read for File {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs
index ac121f1c82e..8eb84b26f22 100644
--- a/src/libstd/sys/unix/fs2.rs
+++ b/src/libstd/sys/unix/fs2.rs
@@ -13,6 +13,7 @@ use io::prelude::*;
 use os::unix::prelude::*;
 
 use ffi::{CString, CStr, OsString, OsStr};
+use fmt;
 use io::{self, Error, SeekFrom};
 use libc::{self, c_int, size_t, off_t, c_char, mode_t};
 use mem;
@@ -294,6 +295,54 @@ 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> {
+            use string::ToString;
+            let mut p = PathBuf::from("/proc/self/fd");
+            p.push(&fd.to_string());
+            readlink(&p).ok()
+        }
+
+        #[cfg(not(target_os = "linux"))]
+        fn get_path(_fd: c_int) -> Option<PathBuf> {
+            // FIXME(#24570): implement this for other Unix platforms
+            None
+        }
+
+        #[cfg(target_os = "linux")]
+        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(target_os = "linux"))]
+        fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
+            // FIXME(#24570): implement this for other Unix platforms
+            None
+        }
+
+        let fd = self.0.raw();
+        let mut b = f.debug_struct("File").field("fd", &fd);
+        if let Some(path) = get_path(fd) {
+            b = b.field("path", &path);
+        }
+        if let Some((read, write)) = get_mode(fd) {
+            b = b.field("read", &read).field("write", &write);
+        }
+        b.finish()
+    }
+}
+
 pub fn mkdir(p: &Path) -> io::Result<()> {
     let p = try!(cstr(p));
     try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) }));
diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs
index 9645c51ec0b..b0515a71229 100644
--- a/src/libstd/sys/windows/fs2.rs
+++ b/src/libstd/sys/windows/fs2.rs
@@ -14,6 +14,7 @@ use os::windows::prelude::*;
 
 use default::Default;
 use ffi::{OsString, AsOsStr};
+use fmt;
 use io::{self, Error, SeekFrom};
 use libc::{self, HANDLE};
 use mem;
@@ -271,6 +272,15 @@ impl FromInner<libc::HANDLE> for File {
     }
 }
 
+impl fmt::Debug for File {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // FIXME(#24570): add more info here (e.g. path, mode)
+        f.debug_struct("File")
+            .field("handle", &self.handle.raw())
+            .finish()
+    }
+}
+
 pub fn to_utf16(s: &Path) -> Vec<u16> {
     s.as_os_str().encode_wide().chain(Some(0).into_iter()).collect()
 }