aboutsummaryrefslogtreecommitdiff
path: root/libbutl/filesystem.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-08-14 13:11:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-08-14 13:11:55 +0200
commit1e2e28d3e442ba3c95a5c2b9e5d920c72f6cee43 (patch)
tree38a998f6769a3898d440ccbe122611c1eb7e59c5 /libbutl/filesystem.cxx
parentd20d2a641351b7f9e8c9bd9b841d8de4d824aa82 (diff)
Add mkanylink() filesystem function
Diffstat (limited to 'libbutl/filesystem.cxx')
-rw-r--r--libbutl/filesystem.cxx56
1 files changed, 56 insertions, 0 deletions
diff --git a/libbutl/filesystem.cxx b/libbutl/filesystem.cxx
index df738ac..b310dd8 100644
--- a/libbutl/filesystem.cxx
+++ b/libbutl/filesystem.cxx
@@ -671,6 +671,62 @@ namespace butl
}
#endif
+ entry_type
+ mkanylink (const path& target, const path& link, bool copy, bool rel)
+ {
+ using error = pair<entry_type, system_error>;
+
+ try
+ {
+ mksymlink (rel ? target.relative (link.directory ()) : target, link);
+ return entry_type::symlink;
+ }
+ catch (system_error& e)
+ {
+ // Note that we are not guaranteed (here and below) that the
+ // system_error exception is of the generic category.
+ //
+ if (e.code ().category () == generic_category ())
+ {
+ int c (e.code ().value ());
+ if (c == ENOSYS || // Not implemented.
+ c == EPERM) // Not supported by the filesystem(s).
+ {
+ try
+ {
+ mkhardlink (target, link);
+ return entry_type::other;
+ }
+ catch (system_error& e)
+ {
+ if (copy && e.code ().category () == generic_category ())
+ {
+ int c (e.code ().value ());
+ if (c == ENOSYS || // Not implemented.
+ c == EPERM || // Not supported by the filesystem(s).
+ c == EXDEV) // On different filesystems.
+ {
+ try
+ {
+ cpfile (target, link);
+ return entry_type::regular;
+ }
+ catch (system_error& e)
+ {
+ throw error (entry_type::regular, move (e));
+ }
+ }
+ }
+
+ throw error (entry_type::other, move (e));
+ }
+ }
+ }
+
+ throw error (entry_type::symlink, move (e));
+ }
+ }
+
// 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