diff options
-rw-r--r-- | libbutl/filesystem.cxx | 26 | ||||
-rw-r--r-- | tests/mventry/testscript | 6 |
2 files changed, 28 insertions, 4 deletions
diff --git a/libbutl/filesystem.cxx b/libbutl/filesystem.cxx index 7b340f6..70597b9 100644 --- a/libbutl/filesystem.cxx +++ b/libbutl/filesystem.cxx @@ -295,7 +295,31 @@ namespace butl if (!CreateHardLinkA (link.string ().c_str (), target.string ().c_str (), nullptr)) - throw_system_error (GetLastError ()); + { + // If creation fails because hardlinks are not supported for the + // specified target/link paths combination, then throw system_error of + // the generic category with an approximate POSIX errno code. This way + // the caller could recognize such a case and, for example, fallback + // to the copy operation. For other error codes use the system + // category. + // + DWORD ec (GetLastError ()); + switch (ec) + { + // Target and link are on different drives. + // + case ERROR_NOT_SAME_DEVICE: throw_generic_error (EXDEV); + + // Target and link are on the same drive, which doesn't support + // hardlinks. + // + case ERROR_ACCESS_DENIED: throw_generic_error (EPERM); + + // Some other failure reason. Fallback to the system category. + // + default: throw_system_error (ec); + } + } } else throw_generic_error (ENOSYS, "directory hard links not supported"); diff --git a/tests/mventry/testscript b/tests/mventry/testscript index 0a0aaa0..826aeef 100644 --- a/tests/mventry/testscript +++ b/tests/mventry/testscript @@ -118,7 +118,7 @@ if ($test.target == $build.host) : rename. : echo 'foo' >=a; - $lns; + $lns &!b; $* b c &c; test -f a; test -f b == 1; @@ -131,7 +131,7 @@ if ($test.target == $build.host) : target stays intact. : echo 'foo' >=a; - $lns &b; + $lns; echo 'bar' >=c &!c; $* c b; cat a >'foo'; @@ -156,7 +156,7 @@ if ($test.target == $build.host) : rename. : mkdir -p a; - $lns; + $lns &!b; $* b c &c; touch a/b; test -f c/b; |