aboutsummaryrefslogtreecommitdiff
path: root/butl/filesystem.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'butl/filesystem.cxx')
-rw-r--r--butl/filesystem.cxx58
1 files changed, 50 insertions, 8 deletions
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)