about summary refs log tree commit diff
path: root/src/libnative/io/file.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnative/io/file.rs')
-rw-r--r--src/libnative/io/file.rs47
1 files changed, 31 insertions, 16 deletions
diff --git a/src/libnative/io/file.rs b/src/libnative/io/file.rs
index cc5b0770d4d..25fb2809e76 100644
--- a/src/libnative/io/file.rs
+++ b/src/libnative/io/file.rs
@@ -10,6 +10,7 @@
 
 //! Blocking posix-based file I/O
 
+use std::sync::arc::UnsafeArc;
 use std::c_str::CString;
 use std::io::IoError;
 use std::io;
@@ -55,9 +56,13 @@ pub fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 {
 
 pub type fd_t = libc::c_int;
 
+struct Inner {
+    fd: fd_t,
+    close_on_drop: bool,
+}
+
 pub struct FileDesc {
-    priv fd: fd_t,
-    priv close_on_drop: bool,
+    priv inner: UnsafeArc<Inner>
 }
 
 impl FileDesc {
@@ -70,7 +75,10 @@ impl FileDesc {
     /// Note that all I/O operations done on this object will be *blocking*, but
     /// they do not require the runtime to be active.
     pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
-        FileDesc { fd: fd, close_on_drop: close_on_drop }
+        FileDesc { inner: UnsafeArc::new(Inner {
+            fd: fd,
+            close_on_drop: close_on_drop
+        }) }
     }
 
     // FIXME(#10465) these functions should not be public, but anything in
@@ -80,7 +88,7 @@ impl FileDesc {
         #[cfg(windows)] type rlen = libc::c_uint;
         #[cfg(not(windows))] type rlen = libc::size_t;
         let ret = retry(|| unsafe {
-            libc::read(self.fd,
+            libc::read(self.fd(),
                        buf.as_ptr() as *mut libc::c_void,
                        buf.len() as rlen) as libc::c_int
         });
@@ -97,7 +105,7 @@ impl FileDesc {
         #[cfg(not(windows))] type wlen = libc::size_t;
         let ret = keep_going(buf, |buf, len| {
             unsafe {
-                libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64
+                libc::write(self.fd(), buf as *libc::c_void, len as wlen) as i64
             }
         });
         if ret < 0 {
@@ -107,7 +115,11 @@ impl FileDesc {
         }
     }
 
-    pub fn fd(&self) -> fd_t { self.fd }
+    pub fn fd(&self) -> fd_t {
+        // This unsafety is fine because we're just reading off the file
+        // descriptor, no one is modifying this.
+        unsafe { (*self.inner.get()).fd }
+    }
 }
 
 impl io::Reader for FileDesc {
@@ -130,7 +142,7 @@ impl rtio::RtioFileStream for FileDesc {
         self.inner_write(buf)
     }
     fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
-        return os_pread(self.fd, buf.as_ptr(), buf.len(), offset);
+        return os_pread(self.fd(), buf.as_ptr(), buf.len(), offset);
 
         #[cfg(windows)]
         fn os_pread(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<int> {
@@ -162,7 +174,7 @@ impl rtio::RtioFileStream for FileDesc {
         }
     }
     fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> {
-        return os_pwrite(self.fd, buf.as_ptr(), buf.len(), offset);
+        return os_pwrite(self.fd(), buf.as_ptr(), buf.len(), offset);
 
         #[cfg(windows)]
         fn os_pwrite(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<()> {
@@ -197,7 +209,7 @@ impl rtio::RtioFileStream for FileDesc {
             io::SeekCur => libc::FILE_CURRENT,
         };
         unsafe {
-            let handle = libc::get_osfhandle(self.fd) as libc::HANDLE;
+            let handle = libc::get_osfhandle(self.fd()) as libc::HANDLE;
             let mut newpos = 0;
             match libc::SetFilePointerEx(handle, pos, &mut newpos, whence) {
                 0 => Err(super::last_error()),
@@ -212,7 +224,7 @@ impl rtio::RtioFileStream for FileDesc {
             io::SeekEnd => libc::SEEK_END,
             io::SeekCur => libc::SEEK_CUR,
         };
-        let n = unsafe { libc::lseek(self.fd, pos as libc::off_t, whence) };
+        let n = unsafe { libc::lseek(self.fd(), pos as libc::off_t, whence) };
         if n < 0 {
             Err(super::last_error())
         } else {
@@ -220,7 +232,7 @@ impl rtio::RtioFileStream for FileDesc {
         }
     }
     fn tell(&self) -> Result<u64, IoError> {
-        let n = unsafe { libc::lseek(self.fd, 0, libc::SEEK_CUR) };
+        let n = unsafe { libc::lseek(self.fd(), 0, libc::SEEK_CUR) };
         if n < 0 {
             Err(super::last_error())
         } else {
@@ -228,7 +240,7 @@ impl rtio::RtioFileStream for FileDesc {
         }
     }
     fn fsync(&mut self) -> Result<(), IoError> {
-        return os_fsync(self.fd);
+        return os_fsync(self.fd());
 
         #[cfg(windows)]
         fn os_fsync(fd: c_int) -> IoResult<()> {
@@ -247,7 +259,7 @@ impl rtio::RtioFileStream for FileDesc {
 
     #[cfg(not(windows))]
     fn datasync(&mut self) -> Result<(), IoError> {
-        return super::mkerr_libc(os_datasync(self.fd));
+        return super::mkerr_libc(os_datasync(self.fd()));
 
         #[cfg(target_os = "macos")]
         fn os_datasync(fd: c_int) -> c_int {
@@ -270,7 +282,7 @@ impl rtio::RtioFileStream for FileDesc {
             Ok(_) => {}, Err(e) => return Err(e),
         };
         let ret = unsafe {
-            let handle = libc::get_osfhandle(self.fd) as libc::HANDLE;
+            let handle = libc::get_osfhandle(self.fd()) as libc::HANDLE;
             match libc::SetEndOfFile(handle) {
                 0 => Err(super::last_error()),
                 _ => Ok(())
@@ -282,7 +294,7 @@ impl rtio::RtioFileStream for FileDesc {
     #[cfg(unix)]
     fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
         super::mkerr_libc(retry(|| unsafe {
-            libc::ftruncate(self.fd, offset as libc::off_t)
+            libc::ftruncate(self.fd(), offset as libc::off_t)
         }))
     }
 }
@@ -294,6 +306,9 @@ impl rtio::RtioPipe for FileDesc {
     fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
         self.inner_write(buf)
     }
+    fn clone(&self) -> ~rtio::RtioPipe {
+        ~FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe
+    }
 }
 
 impl rtio::RtioTTY for FileDesc {
@@ -312,7 +327,7 @@ impl rtio::RtioTTY for FileDesc {
     fn isatty(&self) -> bool { false }
 }
 
-impl Drop for FileDesc {
+impl Drop for Inner {
     fn drop(&mut self) {
         // closing stdio file handles makes no sense, so never do it. Also, note
         // that errors are ignored when closing a file descriptor. The reason