From 1131bc0a0f9d4ce920f239dccbd0fcfe1c940548 Mon Sep 17 00:00:00 2001 From: Chris Wong Date: Sun, 19 Apr 2015 21:27:19 +1200 Subject: [PATCH] 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 --- src/liblibc/lib.rs | 2 ++ src/libstd/fs.rs | 7 +++++ src/libstd/sys/unix/fs2.rs | 49 +++++++++++++++++++++++++++++++++++ src/libstd/sys/windows/fs2.rs | 10 +++++++ 4 files changed, 68 insertions(+) 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 posix01 { 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 @@ fn from_inner(f: fs_imp::File) -> 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 { 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 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 @@ fn from_inner(fd: c_int) -> 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 { + 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 { + // 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 default::Default; use ffi::{OsString, AsOsStr}; +use fmt; use io::{self, Error, SeekFrom}; use libc::{self, HANDLE}; use mem; @@ -271,6 +272,15 @@ fn from_inner(handle: libc::HANDLE) -> 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 { s.as_os_str().encode_wide().chain(Some(0).into_iter()).collect() } -- 2.44.0