diff options
Diffstat (limited to 'butl/fdstream.cxx')
-rw-r--r-- | butl/fdstream.cxx | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/butl/fdstream.cxx b/butl/fdstream.cxx index 41dd1f5..d841cc2 100644 --- a/butl/fdstream.cxx +++ b/butl/fdstream.cxx @@ -71,14 +71,36 @@ namespace butl throw ios_base::failure (m != nullptr ? m : e.message ().c_str ()); } + // Throw system_error with generic_category. + // static inline void - throw_ios_failure (int ev, const char* m = nullptr) + throw_ios_failure (int errno_code, const char* m = nullptr) { - error_code ec (ev, system_category ()); + error_code ec (errno_code, generic_category ()); throw_ios_failure<is_base_of<system_error, ios_base::failure>::value> ( ec, m); } +#ifdef _WIN32 + // Throw system_error with system_category. + // + static inline void + throw_ios_system_failure (int system_code) + { + // Here we work around MinGW libstdc++ that interprets Windows system error + // codes (for example those returned by GetLastError()) as errno codes. + // + // Note that the resulting system_error description will have ': Success.' + // suffix that is stripped by our custom operator<<(ostream, exception). + // + error_code ec (0, system_category ()); + string m (win32::error_msg (system_code)); + + throw_ios_failure<is_base_of<system_error, ios_base::failure>::value> ( + ec, m.c_str ()); + } +#endif + // auto_fd // void auto_fd:: @@ -905,7 +927,7 @@ namespace butl { HANDLE h (reinterpret_cast<HANDLE> (_get_osfhandle (fd))); if (h == INVALID_HANDLE_VALUE) - throw_ios_failure (EIO, "unable to obtain file handle"); + throw_ios_failure (errno); // EBADF (POSIX value). return h; }; @@ -921,7 +943,7 @@ namespace butl DWORD f; if (!GetHandleInformation (handle (fd), &f)) - throw_ios_failure (EIO, last_error_msg ().c_str ()); + throw_ios_system_failure (GetLastError ()); // If the source handle is inheritable then no flag copy is required (as // the duplicate handle will be inheritable by default). @@ -933,7 +955,7 @@ namespace butl auto_fd nfd (dup ()); if (!SetHandleInformation (handle (nfd.get ()), HANDLE_FLAG_INHERIT, 0)) - throw_ios_failure (EIO, last_error_msg ().c_str ()); + throw_ios_system_failure (GetLastError ()); return nfd; } @@ -975,6 +997,10 @@ namespace butl } catch (const system_error& e) { + // Make sure that the error denotes errno portable code. + // + assert (e.code ().category () == generic_category ()); + errno = e.code ().value (); return -1; } @@ -999,7 +1025,7 @@ namespace butl // int r (_setmode (fd, m == fdstream_mode::binary ? _O_BINARY : _O_TEXT)); if (r == -1) - throw_ios_failure (errno); + throw_ios_failure (errno); // EBADF or EINVAL (POSIX values). return fdstream_mode::blocking | ((r & _O_BINARY) == _O_BINARY |