Parcourir la source

pandaFileStream

David Rose il y a 17 ans
Parent
commit
964c76f2e0
46 fichiers modifiés avec 1174 ajouts et 82 suppressions
  1. 1 1
      dtool/src/cppparser/cppPreprocessor.cxx
  2. 10 4
      dtool/src/dtoolutil/Sources.pp
  3. 2 1
      dtool/src/dtoolutil/dtoolutil_composite2.cxx
  4. 3 3
      dtool/src/dtoolutil/executionEnvironment.cxx
  5. 167 0
      dtool/src/dtoolutil/filename.cxx
  6. 6 0
      dtool/src/dtoolutil/filename.h
  7. 173 0
      dtool/src/dtoolutil/pandaFileStream.I
  8. 17 0
      dtool/src/dtoolutil/pandaFileStream.cxx
  9. 93 0
      dtool/src/dtoolutil/pandaFileStream.h
  10. 556 0
      dtool/src/dtoolutil/pandaFileStreamBuf.cxx
  11. 67 0
      dtool/src/dtoolutil/pandaFileStreamBuf.h
  12. 5 5
      dtool/src/interrogate/interrogate.cxx
  13. 1 1
      dtool/src/interrogate/interrogate_module.cxx
  14. 1 1
      dtool/src/interrogatedb/interrogateDatabase.cxx
  15. 2 0
      dtool/src/parser-inc/iostream
  16. 2 2
      dtool/src/prc/configPageManager.cxx
  17. 1 1
      dtool/src/prc/notify.cxx
  18. 2 2
      dtool/src/prckeys/makePrcKey.cxx
  19. 2 2
      dtool/src/prckeys/signPrcFile_src.cxx
  20. 9 9
      panda/src/downloader/decompressor.cxx
  21. 1 1
      panda/src/downloader/downloadDb.cxx
  22. 2 2
      panda/src/downloader/download_utils.cxx
  23. 1 1
      panda/src/downloader/extractor.h
  24. 1 1
      panda/src/downloader/httpChannel.h
  25. 1 1
      panda/src/downloader/multiplexStream.I
  26. 1 1
      panda/src/downloadertools/check_md5.cxx
  27. 2 2
      panda/src/downloadertools/pdecrypt.cxx
  28. 2 2
      panda/src/downloadertools/pencrypt.cxx
  29. 2 2
      panda/src/downloadertools/punzip.cxx
  30. 2 2
      panda/src/downloadertools/pzip.cxx
  31. 1 1
      panda/src/egg/eggData.cxx
  32. 7 7
      panda/src/express/multifile.cxx
  33. 3 3
      panda/src/express/multifile.h
  34. 3 3
      panda/src/express/patchfile.cxx
  35. 3 3
      panda/src/express/patchfile.h
  36. 1 1
      panda/src/express/test_zstream.cxx
  37. 1 1
      panda/src/express/virtualFileMountSystem.cxx
  38. 1 3
      panda/src/gobj/shader.cxx
  39. 1 1
      panda/src/gobj/texture.cxx
  40. 9 3
      panda/src/gobj/vertexDataSaveFile.cxx
  41. 1 1
      panda/src/parametrics/parametricCurve.cxx
  42. 1 1
      panda/src/parametrics/parametricCurveCollection.cxx
  43. 1 1
      panda/src/pnmimage/pnmImageHeader.cxx
  44. 4 4
      panda/src/putil/bamCache.cxx
  45. 1 1
      panda/src/putil/datagramInputFile.h
  46. 1 1
      panda/src/putil/datagramOutputFile.h

+ 1 - 1
dtool/src/cppparser/cppPreprocessor.cxx

@@ -121,7 +121,7 @@ open(const CPPFile &file) {
   assert(_in == NULL);
 
   _file = file;
-  ifstream *in = new ifstream;
+  pifstream *in = new pifstream;
   _in = in;
 
   return _file._filename.open_read(*in);

+ 10 - 4
dtool/src/dtoolutil/Sources.pp

@@ -13,16 +13,19 @@
     config_dtoolutil.h \
     executionEnvironment.I executionEnvironment.h filename.I  \
     filename.h load_dso.h dSearchPath.I dSearchPath.h \
+    pandaFileStream.h pandaFileStream.I \
+    pandaFileStreamBuf.h \
     pandaSystem.h pandaVersion.h \
-    pfstream.h  \
+    pfstream.h pfstream.I pfstreamBuf.h \
     vector_string.h gnu_getopt.c gnu_getopt.h gnu_getopt1.c  \
-    pfstreamBuf.h vector_src.h 
+    vector_src.h 
 
   #define INCLUDED_SOURCES \
     checkPandaVersion.cxx \
     config_dtoolutil.cxx \
     executionEnvironment.cxx filename.cxx load_dso.cxx  \
     dSearchPath.cxx \
+    pandaFileStream.cxx pandaFileStreamBuf.cxx \
     pandaSystem.cxx \
     pfstreamBuf.cxx pfstream.cxx \
     vector_string.cxx
@@ -32,9 +35,12 @@
     config_dtoolutil.h \
     executionEnvironment.I executionEnvironment.h filename.I    \
     filename.h load_dso.h dSearchPath.I dSearchPath.h   \
+    pandaFileStream.h pandaFileStream.I \
+    pandaFileStreamBuf.h \
     pandaSystem.h pandaVersion.h \
-    pfstream.h pfstream.I vector_string.h gnu_getopt.h \
-    pfstreamBuf.h vector_src.cxx vector_src.h
+    pfstream.h pfstream.I pfstreamBuf.h \
+    vector_string.h gnu_getopt.h \
+    vector_src.cxx vector_src.h
 #end lib_target
 
 #begin test_bin_target

+ 2 - 1
dtool/src/dtoolutil/dtoolutil_composite2.cxx

@@ -1,4 +1,5 @@
-
+#include "pandaFileStream.cxx"
+#include "pandaFileStreamBuf.cxx"
 #include "executionEnvironment.cxx"
 #include "vector_string.cxx"
 #include "pfstream.cxx"

+ 3 - 3
dtool/src/dtoolutil/executionEnvironment.cxx

@@ -344,7 +344,7 @@ read_environment_variables() {
   // have a file called /proc/self/environ that may be read to
   // determine all of our environment variables.
 
-  ifstream proc("/proc/self/environ");
+  pifstream proc("/proc/self/environ");
   if (proc.fail()) {
     cerr << "Cannot read /proc/self/environ; environment variables unavailable.\n";
     return;
@@ -405,7 +405,7 @@ read_args() {
 #if defined(HAVE_PROC_SELF_MAPS)
   // This is how you tell whether or not libdtool.so is loaded,
   // and if so, where it was loaded from.
-  ifstream maps("/proc/self/maps");
+  pifstream maps("/proc/self/maps");
   while (!maps.fail() && !maps.eof()) {
     char buffer[PATH_MAX];
     buffer[0] = 0;
@@ -461,7 +461,7 @@ read_args() {
   // /proc/self/cmdline that may be read to determine all of our
   // command-line arguments.
 
-  ifstream proc("/proc/self/cmdline");
+  pifstream proc("/proc/self/cmdline");
   if (proc.fail()) {
     cerr << "Cannot read /proc/self/cmdline; command-line arguments unavailable to config.\n";
     return;

+ 167 - 0
dtool/src/dtoolutil/filename.cxx

@@ -1913,6 +1913,173 @@ open_read_write(fstream &stream) const {
   return (!stream.fail());
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::open_read
+//       Access: Published
+//  Description: Opens the indicated pifstream for reading the file, if
+//               possible.  Returns true if successful, false
+//               otherwise.  This requires the setting of the
+//               set_text()/set_binary() flags to open the file
+//               appropriately as indicated; it is an error to call
+//               open_read() without first calling one of set_text()
+//               or set_binary().
+////////////////////////////////////////////////////////////////////
+bool Filename::
+open_read(pifstream &stream) const {
+  assert(!get_pattern());
+  assert(is_text() || is_binary());
+
+  ios_openmode open_mode = ios::in;
+
+#ifdef HAVE_IOS_BINARY
+  // For some reason, some systems (like Irix) don't define
+  // ios::binary.
+  if (!is_text()) {
+    open_mode |= ios::binary;
+  }
+#endif
+
+  string os_specific = to_os_specific();
+  stream.clear();
+  stream.open(os_specific.c_str(), open_mode);
+  return (!stream.fail());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::open_write
+//       Access: Published
+//  Description: Opens the indicated pifstream for writing the file, if
+//               possible.  Returns true if successful, false
+//               otherwise.  This requires the setting of the
+//               set_text()/set_binary() flags to open the file
+//               appropriately as indicated; it is an error to call
+//               open_read() without first calling one of set_text()
+//               or set_binary().
+//
+//               If truncate is true, the file is truncated to zero
+//               length upon opening it, if it already exists.
+//               Otherwise, the file is kept at its original length.
+////////////////////////////////////////////////////////////////////
+bool Filename::
+open_write(pofstream &stream, bool truncate) const {
+  assert(!get_pattern());
+  assert(is_text() || is_binary());
+
+  ios_openmode open_mode = ios::out;
+
+  if (truncate) {
+    open_mode |= ios::trunc;
+
+  } else {
+    // Some systems insist on having ios::in set to prevent the file
+    // from being truncated when we open it.  Makes ios::trunc kind of
+    // pointless, doesn't it?  On the other hand, setting ios::in also
+    // seems to imply ios::nocreate (!), so we should only set this if
+    // the file already exists.
+    if (exists()) {
+      open_mode |= ios::in;
+    }
+  }
+
+#ifdef HAVE_IOS_BINARY
+  // For some reason, some systems (like Irix) don't define
+  // ios::binary.
+  if (!is_text()) {
+    open_mode |= ios::binary;
+  }
+#endif
+
+  stream.clear();
+  string os_specific = to_os_specific();
+#ifdef HAVE_OPEN_MASK
+  stream.open(os_specific.c_str(), open_mode, 0666);
+#else
+  stream.open(os_specific.c_str(), open_mode);
+#endif
+
+  return (!stream.fail());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::open_append
+//       Access: Published
+//  Description: Opens the indicated pifstream for writing the file, if
+//               possible.  Returns true if successful, false
+//               otherwise.  This requires the setting of the
+//               set_text()/set_binary() flags to open the file
+//               appropriately as indicated; it is an error to call
+//               open_read() without first calling one of set_text()
+//               or set_binary().
+////////////////////////////////////////////////////////////////////
+bool Filename::
+open_append(pofstream &stream) const {
+  assert(!get_pattern());
+  assert(is_text() || is_binary());
+
+  ios_openmode open_mode = ios::app;
+
+#ifdef HAVE_IOS_BINARY
+  // For some reason, some systems (like Irix) don't define
+  // ios::binary.
+  if (!is_text()) {
+    open_mode |= ios::binary;
+  }
+#endif
+
+  stream.clear();
+  string os_specific = to_os_specific();
+#ifdef HAVE_OPEN_MASK
+  stream.open(os_specific.c_str(), open_mode, 0666);
+#else
+  stream.open(os_specific.c_str(), open_mode);
+#endif
+
+  return (!stream.fail());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Filename::open_read_write
+//       Access: Published
+//  Description: Opens the indicated pfstream for read/write access to
+//               the file, if possible.  Returns true if successful,
+//               false otherwise.  This requires the setting of the
+//               set_text()/set_binary() flags to open the file
+//               appropriately as indicated; it is an error to call
+//               open_read_write() without first calling one of
+//               set_text() or set_binary().
+////////////////////////////////////////////////////////////////////
+bool Filename::
+open_read_write(pfstream &stream) const {
+  assert(!get_pattern());
+  assert(is_text() || is_binary());
+
+  ios_openmode open_mode = ios::out | ios::in;
+
+  // Since ios::in also seems to imply ios::nocreate (!), we must
+  // guarantee the file already exists before we try to open it.
+  if (!exists()) {
+    touch();
+  }
+
+#ifdef HAVE_IOS_BINARY
+  // For some reason, some systems (like Irix) don't define
+  // ios::binary.
+  if (!is_text()) {
+    open_mode |= ios::binary;
+  }
+#endif
+
+  stream.clear();
+  string os_specific = to_os_specific();
+#ifdef HAVE_OPEN_MASK
+  stream.open(os_specific.c_str(), open_mode, 0666);
+#else
+  stream.open(os_specific.c_str(), open_mode);
+#endif
+
+  return (!stream.fail());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Filename::touch
 //       Access: Published

+ 6 - 0
dtool/src/dtoolutil/filename.h

@@ -16,6 +16,7 @@
 #define FILENAME_H
 
 #include "dtoolbase.h"
+#include "pandaFileStream.h"
 #include "typeHandle.h"
 #include "register_type.h"
 #include "vector_string.h"
@@ -179,6 +180,11 @@ PUBLISHED:
   bool open_append(ofstream &stream) const;
   bool open_read_write(fstream &stream) const;
 
+  bool open_read(pifstream &stream) const;
+  bool open_write(pofstream &stream, bool truncate = true) const;
+  bool open_append(pofstream &stream) const;
+  bool open_read_write(pfstream &stream) const;
+
   bool chdir() const;
   bool touch() const;
   bool unlink() const;

+ 173 - 0
dtool/src/dtoolutil/pandaFileStream.I

@@ -0,0 +1,173 @@
+// Filename: pandaFileStream.I
+// Created by:  drose (08Sep08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: IFileStream::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE IFileStream::
+IFileStream() : istream(&_buf) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: IFileStream::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE IFileStream::
+IFileStream(const char *filename, ios::openmode mode) : istream(&_buf) {
+  open(filename, mode);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: IFileStream::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE IFileStream::
+~IFileStream() {
+  close();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: IFileStream::open
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void IFileStream::
+open(const char *filename, ios::openmode mode) {
+  clear((ios_iostate)0);
+  _buf.open(filename, mode);
+  if (!_buf.is_open()) {
+    clear(ios::failbit);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: IFileStream::close
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void IFileStream::
+close() {
+  _buf.close();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OFileStream::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE OFileStream::
+OFileStream() : ostream(&_buf) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OFileStream::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE OFileStream::
+OFileStream(const char *filename, ios::openmode mode) : ostream(&_buf) {
+  open(filename, mode);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OFileStream::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE OFileStream::
+~OFileStream() {
+  close();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OFileStream::open
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void OFileStream::
+open(const char *filename, ios::openmode mode) {
+  clear((ios_iostate)0);
+  _buf.open(filename, mode);
+  if (!_buf.is_open()) {
+    clear(ios::failbit);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OFileStream::close
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void OFileStream::
+close() {
+  _buf.close();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FileStream::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE FileStream::
+FileStream() : iostream(&_buf) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FileStream::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE FileStream::
+FileStream(const char *filename, ios::openmode mode) : iostream(&_buf) {
+  open(filename, mode);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FileStream::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE FileStream::
+~FileStream() {
+  close();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FileStream::open
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FileStream::
+open(const char *filename, ios::openmode mode) {
+  clear((ios_iostate)0);
+  _buf.open(filename, mode);
+  if (!_buf.is_open()) {
+    clear(ios::failbit);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: FileStream::close
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void FileStream::
+close() {
+  _buf.close();
+}

+ 17 - 0
dtool/src/dtoolutil/pandaFileStream.cxx

@@ -0,0 +1,17 @@
+// Filename: pandaFileStream.cxx
+// Created by:  drose (08Sep08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pandaFileStream.h"
+
+

+ 93 - 0
dtool/src/dtoolutil/pandaFileStream.h

@@ -0,0 +1,93 @@
+// Filename: pandaFileStream.h
+// Created by:  drose (08Sep08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PANDAFILESTREAM_H
+#define PANDAFILESTREAM_H
+
+#include "dtoolbase.h"
+#include "pandaFileStreamBuf.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : IFileStream
+// Description : Implements a C++ stream object suitable for reading
+//               from files on disk.  This is similar to ifstream, but
+//               it provides low-level support for Panda's
+//               simple-threading implementation (using this interface
+//               will block only the current thread, rather than the
+//               entire process, on I/O waits).
+////////////////////////////////////////////////////////////////////
+class EXPCL_DTOOL IFileStream : public istream {
+public:
+  INLINE IFileStream();
+  INLINE IFileStream(const char *filename, ios::openmode mode = ios::in);
+  INLINE ~IFileStream();
+
+  INLINE void open(const char *filename, ios::openmode mode = ios::in);
+  INLINE void close();
+
+private:
+  PandaFileStreamBuf _buf;
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : OFileStream
+// Description : Implements a C++ stream object suitable for writing
+//               to files on disk.  This is similar to ofstream, but
+//               it provides low-level support for Panda's
+//               simple-threading implementation (using this interface
+//               will block only the current thread, rather than the
+//               entire process, on I/O waits).
+////////////////////////////////////////////////////////////////////
+class EXPCL_DTOOL OFileStream : public ostream {
+public:
+  INLINE OFileStream();
+  INLINE OFileStream(const char *filename, ios::openmode mode = ios::out);
+  INLINE ~OFileStream();
+
+  INLINE void open(const char *filename, ios::openmode mode = ios::out);
+  INLINE void close();
+
+private:
+  PandaFileStreamBuf _buf;
+};
+
+////////////////////////////////////////////////////////////////////
+//       Class : FileStream
+// Description : Implements a C++ stream object suitable for reading
+//               from and/or writing to files on disk.  This is
+//               similar to fstream, but it provides low-level support
+//               for Panda's simple-threading implementation (using
+//               this interface will block only the current thread,
+//               rather than the entire process, on I/O waits).
+////////////////////////////////////////////////////////////////////
+class EXPCL_DTOOL FileStream : public iostream {
+public:
+  INLINE FileStream();
+  INLINE FileStream(const char *filename, ios::openmode mode = ios::in);
+  INLINE ~FileStream();
+
+  INLINE void open(const char *filename, ios::openmode mode = ios::in);
+  INLINE void close();
+
+private:
+  PandaFileStreamBuf _buf;
+};
+
+#include "pandaFileStream.I"
+
+typedef IFileStream pifstream;
+typedef OFileStream pofstream;
+typedef FileStream pfstream;
+
+#endif

+ 556 - 0
dtool/src/dtoolutil/pandaFileStreamBuf.cxx

@@ -0,0 +1,556 @@
+// Filename: pandaFileStreamBuf.cxx
+// Created by:  drose (08Sep08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pandaFileStreamBuf.h"
+#include "memoryHook.h"
+
+#ifndef _WIN32
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#endif  // _WIN32
+
+static const size_t file_buffer_size = 4096;
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+PandaFileStreamBuf::
+PandaFileStreamBuf() {
+  _is_open = false;
+  _open_mode = (ios::openmode)0;
+  
+#ifdef _WIN32
+  // Windows case.
+  _handle = NULL;
+#else
+  _fd = -1;
+#endif  // _WIN32
+
+#ifdef HAVE_IOSTREAM
+  _buffer = (char *)PANDA_MALLOC_ARRAY(file_buffer_size * 2);
+  char *ebuf = _buffer + file_buffer_size * 2;
+  char *mbuf = _buffer + file_buffer_size;
+  setg(_buffer, mbuf, mbuf);
+  setp(mbuf, ebuf);
+
+#else
+  allocate();
+  // Chop the buffer in half.  The bottom half goes to the get buffer;
+  // the top half goes to the put buffer.
+  char *b = base();
+  char *t = ebuf();
+  char *m = b + (t - b) / 2;
+  setg(b, m, m);
+  setp(b, m);
+#endif
+
+  _gpos = 0;
+  _ppos = 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+PandaFileStreamBuf::
+~PandaFileStreamBuf() {
+  close();
+#ifdef HAVE_IOSTREAM
+  PANDA_FREE_ARRAY(_buffer);
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::open
+//       Access: Public
+//  Description: Attempts to open the file for input and/or output.
+////////////////////////////////////////////////////////////////////
+void PandaFileStreamBuf::
+open(const char *filename, ios::openmode mode) {
+  close();
+
+  _filename = filename;
+  _open_mode = mode;
+  _is_open = false;
+
+#ifdef _WIN32
+  // Windows case.
+  DWORD access = 0;
+  if (_open_mode & ios::in) {
+    access |= GENERIC_READ;
+  }
+  if (_open_mode & ios::out) {
+    access |= GENERIC_WRITE;
+  }
+
+  DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+
+  DWORD creation_disposition = 0;
+  if ((_open_mode & (ios::trunc | ios::out)) == (ios::trunc | ios::out)) {
+    creation_disposition = CREATE_ALWAYS;
+  } else if (_open_mode & ios::out) {
+    creation_disposition = OPEN_ALWAYS;
+  } else {
+    creation_disposition = OPEN_EXISTING;
+  }
+
+  DWORD flags = 0;
+
+  if (!(_open_mode & ios::out)) {
+    flags |= FILE_ATTRIBUTE_READONLY;
+  }
+
+#if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
+  // In SIMPLE_THREADS mode, we use "overlapped" I/O.
+  flags |= FILE_FLAG_OVERLAPPED;
+#endif
+
+  _handle = CreateFile(_filename.c_str(), access, share_mode,
+                       NULL, creation_disposition, flags, NULL);
+  if (_handle != INVALID_HANDLE_VALUE) {
+    // The file was successfully opened and locked.
+    _is_open = true;
+  }
+  
+#else
+  // Posix case.
+  int flags = 0;
+
+  if ((_open_mode & (ios::in | ios::out)) == (ios::in | ios::out)) {
+    flags |= O_RDWR | O_CREAT;
+  } else if (_open_mode & ios::in) {
+    flags |= O_RDONLY;
+  } else if (_open_mode & ios::out) {
+    flags |= O_WRONLY | O_CREAT;
+  }
+
+  if (_open_mode & ios::app) {
+    flags |= O_APPEND;
+  }
+
+  if ((_open_mode & (ios::trunc | ios::out)) == (ios::trunc | ios::out)) {
+    flags |= O_TRUNC;
+  }
+
+#if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
+  // In SIMPLE_THREADS mode, we use non-blocking I/O.
+  flags |= O_NONBLOCK;
+#endif
+
+  _fd = ::open(_filename.c_str(), flags, 0666);
+  while (_fd == -1 && errno == EAGAIN) {
+    thread_yield();
+    _fd = ::open(_filename.c_str(), flags, 0666);
+  }
+
+  if (_fd != -1) {
+    _is_open = true;
+  }
+#endif  // _WIN32
+
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::is_open
+//       Access: Public
+//  Description: Returns true if the file is open, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool PandaFileStreamBuf::
+is_open() const {
+  return _is_open;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::close
+//       Access: Public
+//  Description: Empties the buffer and closes the file.
+////////////////////////////////////////////////////////////////////
+void PandaFileStreamBuf::
+close() {
+  // Make sure the write buffer is flushed.
+  sync();
+
+#ifdef _WIN32
+  if (_handle != NULL) {
+    CloseHandle(_handle);
+  }
+  _handle = NULL;
+#else
+  if (_fd != -1) {
+    ::close(_fd);
+  }
+  _fd = -1;
+#endif  // _WIN32
+
+  _is_open = false;
+  _open_mode = (ios::openmode)0;
+
+  _gpos = 0;
+  _ppos = 0;
+
+  pbump(pbase() - pptr());
+  gbump(egptr() - gptr());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::seekoff
+//       Access: Public, Virtual
+//  Description: Implements seeking within the stream.
+////////////////////////////////////////////////////////////////////
+streampos PandaFileStreamBuf::
+seekoff(streamoff off, ios_seekdir dir, ios_openmode which) {
+  streampos result = -1;
+
+  // Sync the iostream buffer first.
+  sync();
+
+  if (which & ios::in) {
+    // Determine the current file position.
+    size_t n = egptr() - gptr();
+    gbump(n);
+    _gpos -= n;
+    size_t cur_pos = _gpos;
+    size_t new_pos = cur_pos;
+    
+    // Now adjust the data pointer appropriately.
+    switch (dir) {
+    case ios::beg:
+      new_pos = (size_t)off;
+      break;
+      
+    case ios::cur:
+      new_pos = (size_t)((int)cur_pos + off);
+      break;
+      
+    case ios::end:
+#ifdef _WIN32
+      // Windows case.
+      {
+        LARGE_INTEGER li;
+        GetFileSizeEx(_handle, &li);
+        new_pos = (streampos)li.QuadPart + off;
+      }
+#else
+      // Posix case.
+      new_pos = lseek(_fd, off, SEEK_END);
+      if (new_pos == -1) {
+        return -1;
+      }
+#endif  // _WIN32
+      break;
+
+    default:
+      // Shouldn't get here.
+      break;
+    }
+
+    _gpos = new_pos;
+    result = new_pos;
+  }
+
+  if (which & ios::out) {
+    // Determine the current file position.
+    size_t n = pptr() - pbase();
+    streampos cur_pos = _ppos + (streamoff)n;
+    streampos new_pos = cur_pos;
+    
+    // Now adjust the data pointer appropriately.
+    switch (dir) {
+    case ios::beg:
+      new_pos = (streampos)off;
+      break;
+      
+    case ios::cur:
+      new_pos = (streampos)((int)cur_pos + off);
+      break;
+      
+    case ios::end:
+#ifdef _WIN32
+      // Windows case.
+      // Windows case.
+      {
+        LARGE_INTEGER li;
+        GetFileSizeEx(_handle, &li);
+        new_pos = (streampos)li.QuadPart + off;
+      }
+#else
+      // Posix case.
+      new_pos = lseek(_fd, off, SEEK_END);
+      if (new_pos == (streampos)-1) {
+        return -1;
+      }
+#endif  // _WIN32
+      break;
+
+    default:
+      // Shouldn't get here.
+      break;
+    }
+
+    _ppos = new_pos;
+    result = new_pos;
+  }
+
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::seekpos
+//       Access: Public, Virtual
+//  Description: A variant on seekoff() to implement seeking within a
+//               stream.
+//
+//               The MSDN Library claims that it is only necessary to
+//               redefine seekoff(), and not seekpos() as well, as the
+//               default implementation of seekpos() is supposed to
+//               map to seekoff() exactly as I am doing here; but in
+//               fact it must do something else, because seeking
+//               didn't work on Windows until I redefined this
+//               function as well.
+////////////////////////////////////////////////////////////////////
+streampos PandaFileStreamBuf::
+seekpos(streampos pos, ios_openmode which) {
+  return seekoff(pos, ios::beg, which);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::overflow
+//       Access: Protected, Virtual
+//  Description: Called by the system ostream implementation when its
+//               internal buffer is filled, plus one character.
+////////////////////////////////////////////////////////////////////
+int PandaFileStreamBuf::
+overflow(int ch) {
+  size_t n = pptr() - pbase();
+  if (n != 0) {
+    write_chars(pbase(), n);
+    pbump(-(int)n);
+  }
+
+  if (ch != EOF) {
+    // Store the extra character back in the buffer.
+    assert(pptr() != epptr());
+    *(pptr()) = ch;
+    pbump(1);
+  }
+
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::sync
+//       Access: Protected, Virtual
+//  Description: Called by the system iostream implementation to
+//               implement a flush operation.
+////////////////////////////////////////////////////////////////////
+int PandaFileStreamBuf::
+sync() {
+  size_t n = pptr() - pbase();
+
+  write_chars(pbase(), n);
+  pbump(-(int)n);
+
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::underflow
+//       Access: Protected, Virtual
+//  Description: Called by the system istream implementation when its
+//               internal buffer needs more characters.
+////////////////////////////////////////////////////////////////////
+int PandaFileStreamBuf::
+underflow() {
+  // Sometimes underflow() is called even if the buffer is not empty.
+  if (gptr() >= egptr()) {
+    // Mark the buffer filled (with buffer_size bytes).
+    size_t buffer_size = egptr() - eback();
+    gbump(-(int)buffer_size);
+
+    size_t num_bytes = buffer_size;
+    size_t read_count = read_chars(gptr(), buffer_size);
+
+    if (read_count != num_bytes) {
+      // Oops, we didn't read what we thought we would.
+      if (read_count == 0) {
+        gbump(num_bytes);
+        return EOF;
+      }
+
+      // Slide what we did read to the top of the buffer.
+      assert(read_count < num_bytes);
+      size_t delta = num_bytes - read_count;
+      memmove(gptr() + delta, gptr(), read_count);
+      gbump(delta);
+    }
+  }
+
+  return (unsigned char)*gptr();
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::read_chars
+//       Access: Private
+//  Description: Attempts to extract the indicated number of
+//               characters from the current file position.  Returns
+//               the number of characters extracted.
+////////////////////////////////////////////////////////////////////
+size_t PandaFileStreamBuf::
+read_chars(char *start, size_t length) {
+  if (length == 0) {
+    return 0;
+  }
+
+  // Make sure the write buffer is flushed.
+  sync();
+  
+#ifdef _WIN32
+  // Windows case.
+  OVERLAPPED overlapped;
+  memset(&overlapped, 0, sizeof(overlapped));
+  LARGE_INTEGER gpos;
+  gpos.QuadPart = _gpos;
+  overlapped.Offset = gpos.LowPart;
+  overlapped.OffsetHigh = gpos.HighPart;
+  
+  DWORD bytes_read = 0;
+  BOOL success = ReadFile(_handle, start, length, &bytes_read, &overlapped);
+  while (!success) {
+    DWORD error = GetLastError();
+    if (error == ERROR_IO_INCOMPLETE || error == ERROR_IO_PENDING) {
+      // Wait for more later.
+      thread_yield();
+    } else if (error == ERROR_HANDLE_EOF) {
+      // End-of-file, normal result.
+      break;
+    } else {
+      cerr
+        << "Error reading " << length
+        << " bytes from " << _filename << ", windows error code 0x" << hex
+        << error << dec << ".\n";
+      return 0;
+    }
+    success = GetOverlappedResult(_handle, &overlapped, &bytes_read, false);
+  }
+
+  length = bytes_read;
+  
+#else
+  // Posix case.
+  if (lseek(_fd, _gpos, SEEK_SET) == -1) {
+    cerr
+      << "Error seeking to position " << _gpos << " in " << _filename << "\n";
+    return 0;
+  }
+  
+  ssize_t result = ::read(_fd, start, length);
+  while (result < 0) {
+    if (errno == EAGAIN) {
+      thread_yield();
+    } else {
+      cerr
+        << "Error reading " << length << " bytes from " << _filename << "\n";
+      return 0;
+    }
+    result = ::read(_fd, start, length);
+  }
+
+  length = result;
+#endif  // _WIN32
+
+  _gpos += length;
+  return length;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PandaFileStreamBuf::write_chars
+//       Access: Private
+//  Description: Outputs the indicated stream of characters to the
+//               current file position.
+////////////////////////////////////////////////////////////////////
+void PandaFileStreamBuf::
+write_chars(const char *start, size_t length) {
+  if (length == 0) {
+    // Trivial no-op.
+    return;
+  }
+
+  // Make sure the read buffer is flushed.
+  size_t n = egptr() - gptr();
+  gbump(n);
+  _gpos -= n;
+  
+#ifdef _WIN32
+  // Windows case.
+  OVERLAPPED overlapped;
+  memset(&overlapped, 0, sizeof(overlapped));
+  LARGE_INTEGER ppos;
+  ppos.QuadPart = _ppos;
+  overlapped.Offset = ppos.LowPart;
+  overlapped.OffsetHigh = ppos.HighPart;
+  
+  DWORD bytes_written = 0;
+  BOOL success = WriteFile(_handle, start, length, &bytes_written, &overlapped);
+  while (!success) {
+    DWORD error = GetLastError();
+    if (error == ERROR_IO_INCOMPLETE || error == ERROR_IO_PENDING) {
+      // Wait for more later.
+      thread_yield();
+    } else {
+      cerr
+        << "Error writing " << length
+        << " bytes to " << _filename << ", windows error code 0x" << hex
+        << error << dec << ".  Disk full?\n";
+      return;
+    }
+    success = GetOverlappedResult(_handle, &overlapped, &bytes_written, false);
+  }
+  assert(bytes_written == length);
+  _ppos += bytes_written;
+  
+#else
+  // Posix case.
+  if (!(_open_mode & ios::app)) {
+    if (lseek(_fd, _ppos, SEEK_SET) == -1) {
+      cerr
+        << "Error seeking to position " << _ppos << " in " << _filename << "\n";
+      return;
+    }
+  }
+  
+  while (length > 0) {
+    ssize_t result = ::write(_fd, start, length);
+    if (result < 0) {
+      if (errno == EAGAIN) {
+        thread_yield();
+      } else {
+        cerr
+          << "Error writing " << length << " bytes to " << _filename << "\n";
+        return;
+      }
+      continue;
+    }
+    
+    start += result;
+    length -= result;
+    _ppos += result;
+  }
+#endif  // _WIN32
+}

+ 67 - 0
dtool/src/dtoolutil/pandaFileStreamBuf.h

@@ -0,0 +1,67 @@
+// Filename: pandaFileStreamBuf.h
+// Created by:  drose (08Sep08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef PANDAFILESTREAMBUF_H
+#define PANDAFILESTREAMBUF_H
+
+#include "dtoolbase.h"
+
+#if defined(_WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+////////////////////////////////////////////////////////////////////
+//       Class : PandaFileStreamBuf
+// Description : The streambuf object that implements
+//               pifstream and pofstream.
+////////////////////////////////////////////////////////////////////
+class EXPCL_DTOOL PandaFileStreamBuf : public streambuf {
+public:
+  PandaFileStreamBuf();
+  virtual ~PandaFileStreamBuf();
+
+  void open(const char *filename, ios::openmode mode);
+  bool is_open() const;
+  void close();
+
+protected:
+  virtual streampos seekoff(streamoff off, ios_seekdir dir, ios_openmode which);
+  virtual streampos seekpos(streampos pos, ios_openmode which);
+
+  virtual int overflow(int c);
+  virtual int sync();
+  virtual int underflow();
+
+private:
+  size_t read_chars(char *start, size_t length);
+  void write_chars(const char *start, size_t length);
+
+private:
+  string _filename;
+  bool _is_open;
+  ios::openmode _open_mode;
+
+#ifdef _WIN32
+  HANDLE _handle;
+#else
+  int _fd;  // Posix file descriptor
+#endif  // _WIN32
+
+  char *_buffer;
+  streampos _ppos;
+  streampos _gpos;
+};
+
+#endif

+ 5 - 5
dtool/src/interrogate/interrogate.cxx

@@ -512,7 +512,7 @@ main(int argc, char *argv[]) {
     Filename nfilename = filename;
     nfilename.set_extension("N");
     nfilename.set_text();
-    ifstream nfile;
+    pifstream nfile;
     if (nfilename.open_read(nfile)) {
       builder.read_command_file(nfile);
     }
@@ -526,8 +526,8 @@ main(int argc, char *argv[]) {
   int file_identifier = time((time_t *)NULL);
   InterrogateModuleDef *def = builder.make_module_def(file_identifier);
     
-  ofstream * the_output_include = NULL;
-  ofstream output_include;
+  pofstream * the_output_include = NULL;
+  pofstream output_include;
   
 
   if (1==2 && !output_include_filename.empty()) 
@@ -556,7 +556,7 @@ main(int argc, char *argv[]) {
   // Now output all of the wrapper functions.
   if (!output_code_filename.empty())
   {
-    ofstream output_code;
+    pofstream output_code;
     output_code_filename.open_write(output_code);
 
     output_code
@@ -585,7 +585,7 @@ main(int argc, char *argv[]) {
 
   // And now output the bulk of the database.
   if (!output_data_filename.empty()) {
-    ofstream output_data;
+    pofstream output_data;
     output_data_filename.open_write(output_data);
 
     if (output_data.fail()) 

+ 1 - 1
dtool/src/interrogate/interrogate_module.cxx

@@ -340,7 +340,7 @@ int main(int argc, char *argv[])
   // Now output the table.
   if (!output_code_filename.empty()) 
   {
-    ofstream output_code;
+    pofstream output_code;
 
     if (!output_code_filename.open_write(output_code)) 
     {

+ 1 - 1
dtool/src/interrogatedb/interrogateDatabase.cxx

@@ -911,7 +911,7 @@ load_latest() {
 
       } else {
 
-        ifstream input;
+        pifstream input;
         pathname.set_text();
         if (!pathname.open_read(input)) {
           interrogatedb_cat->error() << "Unable to read " << pathname << ".\n";

+ 2 - 0
dtool/src/parser-inc/iostream

@@ -34,6 +34,8 @@ __published:
     cur = 1,
     end = 2,
   };
+  enum openmode {
+  };
 };
 class ios : public ios_base {
 __published:

+ 2 - 2
dtool/src/prc/configPageManager.cxx

@@ -309,7 +309,7 @@ reload_implicit_pages() {
       // Read and decrypt the file.
       filename.set_binary();
       
-      ifstream in;
+      pifstream in;
       if (!filename.open_read(in)) {
         prc_cat.error()
           << "Unable to read " << filename << "\n";
@@ -326,7 +326,7 @@ reload_implicit_pages() {
       // Just read the file.
       filename.set_text();
       
-      ifstream in;
+      pifstream in;
       if (!filename.open_read(in)) {
         prc_cat.error()
           << "Unable to read " << filename << "\n";

+ 1 - 1
dtool/src/prc/notify.cxx

@@ -540,7 +540,7 @@ config_initialized() {
       } else {
         Filename filename = notify_output;
         filename.set_text();
-        ofstream *out = new ofstream;
+        pofstream *out = new pofstream;
         if (!filename.open_write(*out)) {
           nout << "Unable to open file " << filename << " for output.\n";
           delete out;

+ 2 - 2
dtool/src/prckeys/makePrcKey.cxx

@@ -144,7 +144,7 @@ write_public_keys(Filename outfile) {
   outfile.set_text();
   cerr << "Rewriting " << outfile << "\n";
 
-  ofstream out;
+  pofstream out;
   if (!outfile.open_write(out)) {
     cerr << "Unable to open " << outfile << " for writing.\n";
     exit(1);
@@ -212,7 +212,7 @@ write_private_key(EVP_PKEY *pkey, Filename outfile, int n, time_t now,
   outfile.set_text();
   cerr << "Rewriting " << outfile << "\n";
 
-  ofstream out;
+  pofstream out;
   if (!outfile.open_write(out)) {
     cerr << "Unable to open " << outfile << " for writing.\n";
     exit(1);

+ 2 - 2
dtool/src/prckeys/signPrcFile_src.cxx

@@ -155,7 +155,7 @@ void
 sign_prc(Filename filename, bool no_comments, EVP_PKEY *pkey) {
   filename.set_text();
 
-  ifstream in;
+  pifstream in;
   if (!filename.open_read(in)) {
     cerr << "Unable to read file " << filename << "\n";
     exit(1);
@@ -223,7 +223,7 @@ sign_prc(Filename filename, bool no_comments, EVP_PKEY *pkey) {
 
   // Now open the file in write mode and rewrite it with the new
   // signature.
-  ofstream out;
+  pofstream out;
   if (!filename.open_write(out)) {
     cerr << "Unable to rewrite file " << filename << "\n";
     exit(1);

+ 9 - 9
panda/src/downloader/decompressor.cxx

@@ -92,30 +92,30 @@ initiate(const Filename &source_file, const Filename &dest_file) {
   _source_filename = Filename(source_file);
   _source_filename.set_binary();
 
-  ifstream *source_fstream = new ifstream;
-  _source = source_fstream;
-  if (!_source_filename.open_read(*source_fstream)) {
+  pifstream *source_pfstream = new pifstream;
+  _source = source_pfstream;
+  if (!_source_filename.open_read(*source_pfstream)) {
     downloader_cat.error()
       << "Unable to read " << _source_filename << "\n";
     return get_write_error();
   }
 
   // Determine source file length
-  source_fstream->seekg(0, ios::end);
-  _source_length = source_fstream->tellg();
+  source_pfstream->seekg(0, ios::end);
+  _source_length = source_pfstream->tellg();
   if (_source_length == 0) {
     downloader_cat.warning()
       << "Zero length file: " << source_file << "\n";
     return EU_error_file_empty;
   }
-  source_fstream->seekg(0, ios::beg);
+  source_pfstream->seekg(0, ios::beg);
 
   // Open destination file
   Filename dest_filename(dest_file);
   dest_filename.set_binary();
 
-  ofstream *dest_fstream = new ofstream;
-  _dest = dest_fstream;
+  pofstream *dest_pfstream = new pofstream;
+  _dest = dest_pfstream;
   if (dest_filename.exists()) {
     downloader_cat.info()
       << dest_filename << " already exists, removing.\n";
@@ -130,7 +130,7 @@ initiate(const Filename &source_file, const Filename &dest_file) {
         << dest_filename << " does not already exist.\n";
     }
   }
-  if (!dest_filename.open_write(*dest_fstream, true)) {
+  if (!dest_filename.open_write(*dest_pfstream, true)) {
     downloader_cat.error()
       << "Unable to write to " << dest_filename << "\n";
     return get_write_error();

+ 1 - 1
panda/src/downloader/downloadDb.cxx

@@ -362,7 +362,7 @@ read_db(Ramfile &file, bool want_server_info) {
 ////////////////////////////////////////////////////////////////////
 bool DownloadDb::
 write_db(Filename &file, Db db, bool want_server_info) {
-  ofstream write_stream;
+  pofstream write_stream;
   file.set_binary();
   if (!file.open_write(write_stream)) {
     downloader_cat.error()

+ 2 - 2
panda/src/downloader/download_utils.cxx

@@ -22,7 +22,7 @@
 
 unsigned long
 check_crc(Filename name) {
-  ifstream read_stream;
+  pifstream read_stream;
   name.set_binary();
   if (!name.open_read(read_stream)) {
     downloader_cat.error()
@@ -48,7 +48,7 @@ check_crc(Filename name) {
 
 unsigned long
 check_adler(Filename name) {
-  ifstream read_stream;
+  pifstream read_stream;
   name.set_binary();
   if (!name.open_read(read_stream)) {
     downloader_cat.error()

+ 1 - 1
panda/src/downloader/extractor.h

@@ -73,7 +73,7 @@ private:
   size_t _subfile_length;
   size_t _total_bytes_extracted;
   istream *_read;
-  ofstream _write;
+  pofstream _write;
   Filename _subfile_filename;
 };
 

+ 1 - 1
panda/src/downloader/httpChannel.h

@@ -346,7 +346,7 @@ private:
   DownloadDest _download_dest;
   bool _subdocument_resumes;
   Filename _download_to_filename;
-  ofstream _download_to_file;
+  pofstream _download_to_file;
   Ramfile *_download_to_ramfile;
 
   int _read_index;

+ 1 - 1
panda/src/downloader/multiplexStream.I

@@ -72,7 +72,7 @@ add_standard_output() {
 INLINE bool MultiplexStream::
 add_file(Filename file) {
   file.set_text();
-  ofstream *out = new ofstream;
+  pofstream *out = new pofstream;
   if (!file.open_append(*out)) {
     delete out;
     return false;

+ 1 - 1
panda/src/downloadertools/check_md5.cxx

@@ -25,7 +25,7 @@
 
 bool output_decimal = false;
 bool suppress_filename = false;
-ofstream binary_output;
+pofstream binary_output;
 
 void
 usage() {

+ 2 - 2
panda/src/downloadertools/pdecrypt.cxx

@@ -129,7 +129,7 @@ main(int argc, char *argv[]) {
       }
 
       // Open source file
-      ifstream read_stream;
+      pifstream read_stream;
       source_file.set_binary();
       if (!source_file.open_read(read_stream)) {
         cerr << "Couldn't read: " << source_file << endl;
@@ -137,7 +137,7 @@ main(int argc, char *argv[]) {
 
       } else {
         // Open destination file
-        ofstream write_stream;
+        pofstream write_stream;
         dest_file.set_binary();
         if (!dest_file.open_write(write_stream, true)) {
           cerr << "Failed to open: " << dest_file << endl;

+ 2 - 2
panda/src/downloadertools/pencrypt.cxx

@@ -186,7 +186,7 @@ main(int argc, char *argv[]) {
       }
 
       // Open source file
-      ifstream read_stream;
+      pifstream read_stream;
       source_file.set_binary();
       if (!source_file.open_read(read_stream)) {
         cerr << "Couldn't read: " << source_file << endl;
@@ -194,7 +194,7 @@ main(int argc, char *argv[]) {
 
       } else {
         // Open destination file
-        ofstream write_stream;
+        pofstream write_stream;
         dest_file.set_binary();
         if (!dest_file.open_write(write_stream, true)) {
           cerr << "Failed to open: " << dest_file << endl;

+ 2 - 2
panda/src/downloadertools/punzip.cxx

@@ -110,7 +110,7 @@ main(int argc, char *argv[]) {
       }
 
       // Open source file
-      ifstream read_stream;
+      pifstream read_stream;
       source_file.set_binary();
       if (!source_file.open_read(read_stream)) {
         cerr << "Couldn't read: " << source_file << endl;
@@ -118,7 +118,7 @@ main(int argc, char *argv[]) {
 
       } else {
         // Open destination file
-        ofstream write_stream;
+        pofstream write_stream;
         dest_file.set_binary();
         if (!dest_file.open_write(write_stream, true)) {
           cerr << "Failed to open: " << dest_file << endl;

+ 2 - 2
panda/src/downloadertools/pzip.cxx

@@ -125,7 +125,7 @@ main(int argc, char *argv[]) {
       }
 
       // Open source file
-      ifstream read_stream;
+      pifstream read_stream;
       source_file.set_binary();
       if (!source_file.open_read(read_stream)) {
         cerr << "Couldn't read: " << source_file << endl;
@@ -133,7 +133,7 @@ main(int argc, char *argv[]) {
 
       } else {
         // Open destination file
-        ofstream write_stream;
+        pofstream write_stream;
         dest_file.set_binary();
         if (!dest_file.open_write(write_stream, true)) {
           cerr << "Failed to open: " << dest_file << endl;

+ 1 - 1
panda/src/egg/eggData.cxx

@@ -249,7 +249,7 @@ write_egg(Filename filename) {
   }
 #endif  // HAVE_ZLIB
 
-  ofstream file;
+  pofstream file;
   if (!filename.open_write(file)) {
     egg_cat.error() << "Unable to open " << filename << " for writing.\n";
     return false;

+ 7 - 7
panda/src/express/multifile.cxx

@@ -705,7 +705,7 @@ repack() {
   }
   Filename temp_filename = Filename::temporary(dirname, "mftemp");
   temp_filename.set_binary();
-  ofstream temp;
+  pofstream temp;
   if (!temp_filename.open_write(temp)) {
     express_cat.info()
       << "Unable to open temporary file " << temp_filename << "\n";
@@ -1028,7 +1028,7 @@ get_subfile_internal_length(int index) const {
 //  Description: Returns an istream that may be used to read the
 //               indicated subfile.  You may seek() within this
 //               istream to your heart's content; even though it will
-//               be a reference to the already-opened fstream of the
+//               be a reference to the already-opened pfstream of the
 //               Multifile itself, byte 0 appears to be the beginning
 //               of the subfile and EOF appears to be the end of the
 //               subfile.
@@ -1132,7 +1132,7 @@ extract_subfile(int index, const Filename &filename) {
   Filename fname = filename;
   fname.set_binary();
   fname.make_dir();
-  ofstream out;
+  pofstream out;
   if (!fname.open_write(out, true)) {
     express_cat.info()
       << "Unable to write to file " << filename << "\n";
@@ -1194,7 +1194,7 @@ compare_subfile(int index, const Filename &filename) {
     return false;
   }
 
-  ifstream in2;
+  pifstream in2;
   Filename bin_filename = Filename::binary_filename(filename);
   if (!bin_filename.open_read(in2)) {
     express_cat.info()
@@ -1752,7 +1752,7 @@ write_data(ostream &write, istream *read, streampos fpos,
   nassertr(write.tellp() == fpos, fpos);
 
   istream *source = _source;
-  ifstream source_file;
+  pifstream source_file;
   if (source == (istream *)NULL && !_source_filename.empty()) {
     // If we have a filename, open it up and read that.
     if (!_source_filename.open_read(source_file)) {
@@ -1871,7 +1871,7 @@ write_data(ostream &write, istream *read, streampos fpos,
 ////////////////////////////////////////////////////////////////////
 //     Function: Multifile::Subfile::rewrite_index_data_start
 //       Access: Public
-//  Description: Seeks within the indicate fstream back to the index
+//  Description: Seeks within the indicate pfstream back to the index
 //               record and rewrites just the _data_start and
 //               _data_length part of the index record.
 ////////////////////////////////////////////////////////////////////
@@ -1901,7 +1901,7 @@ rewrite_index_data_start(ostream &write, Multifile *multifile) {
 ////////////////////////////////////////////////////////////////////
 //     Function: Multifile::Subfile::rewrite_index_flags
 //       Access: Public
-//  Description: Seeks within the indicate fstream back to the index
+//  Description: Seeks within the indicate pfstream back to the index
 //               record and rewrites just the _flags part of the
 //               index record.
 ////////////////////////////////////////////////////////////////////

+ 3 - 3
panda/src/express/multifile.h

@@ -177,9 +177,9 @@ private:
   bool _encryption_flag;
   string _encryption_password;
 
-  ifstream _read_file;
-  ofstream _write_file;
-  fstream _read_write_file;
+  pifstream _read_file;
+  pofstream _write_file;
+  pfstream _read_write_file;
   Filename _multifile_name;
 
   int _file_major_ver;

+ 3 - 3
panda/src/express/patchfile.cxx

@@ -1397,7 +1397,7 @@ build(Filename file_orig, Filename file_new, Filename patch_name) {
   patch_name.set_binary();
 
   // Open the original file for read
-  ifstream stream_orig;
+  pifstream stream_orig;
   file_orig.set_binary();
   if (!file_orig.open_read(stream_orig)) {
     express_cat.error()
@@ -1406,7 +1406,7 @@ build(Filename file_orig, Filename file_new, Filename patch_name) {
   }
 
   // Open the new file for read
-  ifstream stream_new;
+  pifstream stream_new;
   file_new.set_binary();
   if (!file_new.open_read(stream_new)) {
     express_cat.error()
@@ -1415,7 +1415,7 @@ build(Filename file_orig, Filename file_new, Filename patch_name) {
   }
 
   // Open patch file for write
-  ofstream write_stream;
+  pofstream write_stream;
   if (!patch_name.open_write(write_stream)) {
     express_cat.error()
       << "Patchfile::build() - Failed to open file: " << patch_name << endl;

+ 3 - 3
panda/src/express/patchfile.h

@@ -175,9 +175,9 @@ protected:
   PN_uint32 _total_bytes_to_process;
   PN_uint32 _total_bytes_processed;
 
-  ifstream _patch_stream;
-  ofstream _write_stream;
-  ifstream _origfile_stream;
+  pifstream _patch_stream;
+  pofstream _write_stream;
+  pifstream _origfile_stream;
 
   Filename _patch_file;
   Filename _orig_file;

+ 1 - 1
panda/src/express/test_zstream.cxx

@@ -128,7 +128,7 @@ main(int argc, char *argv[]) {
   Filename source_filename = argv[1];
   source_filename.set_binary();
 
-  ifstream source;
+  pifstream source;
 
   if (!source_filename.open_read(source)) {
     cerr << "Unable to open source " << source_filename << ".\n";

+ 1 - 1
panda/src/express/virtualFileMountSystem.cxx

@@ -103,7 +103,7 @@ open_read_file(const Filename &file) const {
 #endif  // WIN32
   Filename pathname(_physical_filename, file);
   pathname.set_binary();
-  ifstream *stream = new ifstream;
+  pifstream *stream = new pifstream;
   if (!pathname.open_read(*stream)) {
     // Couldn't open the file for some reason.
     close_read_file(stream);

+ 1 - 3
panda/src/gobj/shader.cxx

@@ -16,8 +16,6 @@
 #include "shader.h"
 #include "preparedGraphicsObjects.h"
 #include "virtualFileSystem.h"
-#include <iostream>
-#include <fstream>
 
 #ifdef HAVE_CG
 #include "Cg/cg.h"
@@ -1511,7 +1509,7 @@ make(const string &body) {
     fns << "genshader" << index;
     string fn = fns.str();
     gobj_cat.warning() << "Dumping shader: " << fn << "\n";
-    ofstream s;
+    pofstream s;
     s.open(fn.c_str());
     s << body;
     s.close();

+ 1 - 1
panda/src/gobj/texture.cxx

@@ -4482,7 +4482,7 @@ read_dds_file(const Filename &fullpath, bool header_only) {
 bool Texture::
 write_txo_file(const Filename &fullpath) const {
   Filename filename = Filename::binary_filename(fullpath);
-  ofstream out;
+  pofstream out;
   if (!filename.open_write(out)) {
     gobj_cat.error()
       << "Unable to open " << filename << "\n";

+ 9 - 3
panda/src/gobj/vertexDataSaveFile.cxx

@@ -100,7 +100,12 @@ VertexDataSaveFile(const Filename &directory, const string &prefix,
     flags |= O_NONBLOCK;
 #endif
 
-    _fd = open(os_specific.c_str(), flags, 0666);
+    _fd = ::open(os_specific.c_str(), flags, 0666);
+    while (_fd == -1 && errno == EAGAIN) {
+      Thread::force_yield();
+      _fd = ::open(os_specific.c_str(), flags, 0666);
+    }
+
     if (_fd == -1) {
       // Couldn't open the file: permissions problem or bad directory.
       if (!_filename.exists()) {
@@ -230,12 +235,12 @@ write_data(const unsigned char *data, size_t size, bool compressed) {
     if (lseek(_fd, block->get_start(), SEEK_SET) == -1) {
       gobj_cat.error()
         << "Error seeking to position " << block->get_start() << " in save file.\n";
-      return false;
+      return NULL;
     }
 
     while (size > 0) {
       ssize_t result = ::write(_fd, data, size);
-      if (result == -1) {
+      if (result < 0) {
         if (errno == EAGAIN) {
           Thread::force_yield();
         } else {
@@ -243,6 +248,7 @@ write_data(const unsigned char *data, size_t size, bool compressed) {
             << "Error writing " << size << " bytes to save file.  Disk full?\n";
           return NULL;
         }
+        continue;
       }
 
       Thread::consider_yield();

+ 1 - 1
panda/src/parametrics/parametricCurve.cxx

@@ -363,7 +363,7 @@ stitch(const ParametricCurve *, const ParametricCurve *) {
 ////////////////////////////////////////////////////////////////////
 bool ParametricCurve::
 write_egg(Filename filename, CoordinateSystem cs) {
-  ofstream out;
+  pofstream out;
   filename.set_text();
 
   if (!filename.open_write(out)) {

+ 1 - 1
panda/src/parametrics/parametricCurveCollection.cxx

@@ -745,7 +745,7 @@ write(ostream &out, int indent_level) const {
 ////////////////////////////////////////////////////////////////////
 bool ParametricCurveCollection::
 write_egg(Filename filename, CoordinateSystem cs) {
-  ofstream out;
+  pofstream out;
   filename.set_text();
 
   if (!filename.open_write(out)) {

+ 1 - 1
panda/src/pnmimage/pnmImageHeader.cxx

@@ -285,7 +285,7 @@ make_writer(const Filename &filename, PNMFileType *type) const {
     }
 
   } else {
-    ofstream *new_ostream = new ofstream;
+    pofstream *new_ostream = new pofstream;
     Filename actual_name = Filename::binary_filename(filename);
     if (!actual_name.open_write(*new_ostream)) {
       delete new_ostream;

+ 4 - 4
panda/src/putil/bamCache.cxx

@@ -216,7 +216,7 @@ store(BamCacheRecord *record) {
   temp_pathname.set_extension(extension);
   temp_pathname.set_binary();
 
-  ofstream temp_file;
+  pofstream temp_file;
   if (!temp_pathname.open_write(temp_file)) {
     util_cat.error()
       << "Could not open cache file: " << temp_pathname << "\n";
@@ -660,7 +660,7 @@ do_read_index(Filename &index_pathname) {
   }
 
   index_pathname.set_binary();
-  ifstream index_file;
+  pifstream index_file;
   if (!index_pathname.open_read(index_file)) {
     util_cat.error()
       << "Could not open index file: " << index_pathname << "\n";
@@ -725,7 +725,7 @@ do_read_index(Filename &index_pathname) {
 bool BamCache::
 do_write_index(Filename &index_pathname, const BamCacheIndex *index) {
   index_pathname.set_binary();
-  ofstream index_file;
+  pofstream index_file;
   
   if (!index_pathname.open_write(index_file)) {
     util_cat.error()
@@ -851,7 +851,7 @@ read_record(const Filename &source_pathname,
 PT(BamCacheRecord) BamCache::
 do_read_record(Filename &cache_pathname, bool read_data) {
   cache_pathname.set_binary();
-  ifstream cache_file;
+  pifstream cache_file;
   if (!cache_pathname.open_read(cache_file)) {
     util_cat.debug()
       << "Could not open cache file: " << cache_pathname << "\n";

+ 1 - 1
panda/src/putil/datagramInputFile.h

@@ -48,7 +48,7 @@ private:
   bool _read_first_datagram;
   bool _error;
   PT(VirtualFile) _vfile;
-  ifstream _in_file;
+  pifstream _in_file;
   istream *_in;
   bool _owns_in;
 };

+ 1 - 1
panda/src/putil/datagramOutputFile.h

@@ -42,7 +42,7 @@ public:
 private:
   bool _wrote_first_datagram;
   bool _error;
-  ofstream _out_file;
+  pofstream _out_file;
   ostream *_out;
   bool _owns_out;
 };