aboutsummaryrefslogtreecommitdiff
path: root/butl/fdstream.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-08-03 09:01:56 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-08-03 09:01:56 +0200
commit31b87d3d695e35c1daf1c88d2b5d6ddebec3e62b (patch)
tree2494e235616c3bf5dcd15c5ef6780585ed5ef8c0 /butl/fdstream.cxx
parent614d23129684f96ff0c5d77ee9c5a29be1f44272 (diff)
Implement faster emulation of Windows NUL via temporary file
Diffstat (limited to 'butl/fdstream.cxx')
-rw-r--r--butl/fdstream.cxx34
1 files changed, 32 insertions, 2 deletions
diff --git a/butl/fdstream.cxx b/butl/fdstream.cxx
index f761e7b..cff9b59 100644
--- a/butl/fdstream.cxx
+++ b/butl/fdstream.cxx
@@ -21,6 +21,7 @@
#include <errno.h> // errno, E*
#include <ios> // ios_base::openmode, ios_base::failure
+#include <new> // bad_alloc
#include <limits> // numeric_limits
#include <cassert>
#include <exception> // uncaught_exception()
@@ -542,9 +543,38 @@ namespace butl
}
int
- fdnull () noexcept
+ fdnull (bool temp) noexcept
{
- return _sopen ("nul", _O_RDWR, _SH_DENYNO);
+ // No need to translate /r/n before sending it to void.
+ //
+ if (!temp)
+ return _sopen ("nul", _O_RDWR | _O_BINARY, _SH_DENYNO);
+
+ try
+ {
+ // We could probably implement a Windows-specific version of getting
+ // the temporary file that avoid any allocations and exceptions.
+ //
+ path p (path::temp_path ("null")); // Can throw.
+ return _sopen (p.string ().c_str (),
+ (_O_CREAT |
+ _O_RDWR |
+ _O_BINARY | // Don't translate.
+ _O_TEMPORARY | // Remove on close.
+ _O_SHORT_LIVED), // Don't flush to disk.
+ _SH_DENYNO,
+ _S_IREAD | _S_IWRITE);
+ }
+ catch (const bad_alloc&)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ catch (const system_error& e)
+ {
+ errno = e.code ().value ();
+ return -1;
+ }
}
fdstream_mode