diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2017-02-17 09:27:02 +0000 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2017-02-17 16:25:55 +0300 |
commit | 3f2323dae243d7654d3319fe7f53b87062b0d62e (patch) | |
tree | 0ea14477825fb301365989460d02150ccf74711b /butl | |
parent | 9f7edcab2b1e4bd2c8bd7abc6284bfb7dca86ed2 (diff) |
Fix cpfile() to throw system_error only
Diffstat (limited to 'butl')
-rw-r--r-- | butl/fdstream.cxx | 9 | ||||
-rw-r--r-- | butl/filesystem.cxx | 58 |
2 files changed, 54 insertions, 13 deletions
diff --git a/butl/fdstream.cxx b/butl/fdstream.cxx index e28eb0f..bdbfa08 100644 --- a/butl/fdstream.cxx +++ b/butl/fdstream.cxx @@ -39,8 +39,8 @@ namespace butl // throw_ios_failure // template <bool v> - static inline void - throw_ios_failure (error_code e, typename enable_if<v, const char*>::type m) + static inline typename enable_if<v>::type + throw_ios_failure (error_code e, const char* m) { // The idea here is to make an error code to be saved into failure // exception and to make a string returned by what() to contain the error @@ -57,9 +57,8 @@ namespace butl } template <bool v> - static inline void - throw_ios_failure (error_code e, - typename enable_if<!v, const char*>::type m) + static inline typename enable_if<!v>::type + throw_ios_failure (error_code e, const char* m) { throw ios_base::failure (m != nullptr ? m : e.message ().c_str ()); } diff --git a/butl/filesystem.cxx b/butl/filesystem.cxx index 1553324..e792bef 100644 --- a/butl/filesystem.cxx +++ b/butl/filesystem.cxx @@ -288,10 +288,18 @@ namespace butl } #endif - void - cpfile (const path& from, const path& to, cpflags fl) + // For I/O operations cpfile() can throw ios_base::failure exception that is + // not derived from system_error for old versions of g++ (as of 4.9). From + // the other hand cpfile() must throw system_error only. Let's catch + // ios_base::failure and rethrow as system_error in such a case. + // + template <bool v> + static inline typename enable_if<v>::type + cpfile (const path& from, const path& to, + cpflags fl, + permissions perm, + auto_rmfile& rm) { - permissions perm (path_permissions (from)); ifdstream ifs (from, fdopen_mode::binary); fdopen_mode om (fdopen_mode::out | @@ -302,11 +310,6 @@ namespace butl if ((fl & cpflags::overwrite_content) != cpflags::overwrite_content) om |= fdopen_mode::exclusive; - // Create prior to the output file stream creation so that the file is - // removed after it is closed. - // - auto_rmfile rm; - ofdstream ofs (fdopen (to, om, perm)); rm = auto_rmfile (to); @@ -321,6 +324,45 @@ namespace butl ifs.close (); // Throws ios::failure on failure. ofs.close (); // Throws ios::failure on flush/close failure. + } + + template <bool v> + static inline typename enable_if<!v>::type + cpfile (const path& from, const path& to, + cpflags fl, + permissions perm, + auto_rmfile& rm) + { + try + { + cpfile<true> (from, to, fl, perm, rm); + } + catch (const ios_base::failure& e) + { + // While we try to preserve the original error information, we can not + // make the description to be exactly the same, for example + // + // Is a directory + // + // becomes + // + // Is a directory: Input/output error + // + // Note that our custom operator<<(ostream, exception) doesn't strip this + // suffix. This is a temporary code after all. + // + throw system_error (EIO, system_category (), e.what ()); + } + } + + void + cpfile (const path& from, const path& to, cpflags fl) + { + permissions perm (path_permissions (from)); + auto_rmfile rm; + + cpfile<is_base_of<system_error, ios_base::failure>::value> ( + from, to, fl, perm, rm); if ((fl & cpflags::overwrite_permissions) == cpflags::overwrite_permissions) |