aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-04-28 18:04:08 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-04-28 18:04:08 +0200
commit8a82f67e2cb3366ab6988bcb56eb06c1d56fdc5d (patch)
tree5fa3a73d0769d9426fc647228cddd19fd52a1fc9
parent9c8844e80d493eceaa706c1e4cdf983f7e32c59d (diff)
Use rmsymlink() to portably remove symlinks
-rw-r--r--build2/algorithm.cxx23
-rw-r--r--build2/filesystem.cxx27
-rw-r--r--build2/filesystem.hxx3
3 files changed, 45 insertions, 8 deletions
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index 6f756e4..924935c 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -973,7 +973,12 @@ namespace build2
try
{
- try_rmfile (l); // Normally will be there.
+ // Normally will be there.
+ //
+ if (l.to_directory ())
+ try_rmsymlink (l, true /* directory */);
+ else
+ try_rmfile (l);
// Skip (ad hoc) targets that don't exist.
//
@@ -1014,10 +1019,10 @@ namespace build2
void
clean_backlink (const path& l, uint16_t verbosity)
{
- // Assuming this works for directories (which can only be symlinked). See
- // also try_rmfile() calls in ~backlink() and update_backlink().
- //
- rmfile (l, verbosity);
+ if (l.to_directory ())
+ rmsymlink (l, true /* directory */, verbosity);
+ else
+ rmfile (l, verbosity); // Should work for symbolic and hard file links.
}
// If target/link path are syntactically to a directory, then the backlink
@@ -1039,9 +1044,11 @@ namespace build2
{
if (active)
{
- // Assuming this works for both file and directory (sym)links.
- //
- try_rmfile (path, true /* ignore_errors */);
+ if (path.to_directory ())
+ try_rmsymlink (path, true /* directory */, true /* ignore_errors */);
+ else
+ try_rmfile (path, true /* ignore_errors */);
+
active = false;
}
}
diff --git a/build2/filesystem.cxx b/build2/filesystem.cxx
index 58e3037..bfda1c4 100644
--- a/build2/filesystem.cxx
+++ b/build2/filesystem.cxx
@@ -85,6 +85,33 @@ namespace build2
return ms;
}
+ fs_status<rmfile_status>
+ rmsymlink (const path& p, bool d, uint16_t v)
+ {
+ auto print = [&p, v] ()
+ {
+ if (verb >= v)
+ text << "rm " << p.string ();
+ };
+
+ rmfile_status rs;
+
+ try
+ {
+ rs = try_rmsymlink (p, d);
+ }
+ catch (const system_error& e)
+ {
+ print ();
+ fail << "unable to remove symlink " << p.string () << ": " << e << endf;
+ }
+
+ if (rs == rmfile_status::success)
+ print ();
+
+ return rs;
+ }
+
fs_status<butl::rmdir_status>
rmdir_r (const dir_path& d, bool dir, uint16_t v)
{
diff --git a/build2/filesystem.hxx b/build2/filesystem.hxx
index 4c118a1..bbdc560 100644
--- a/build2/filesystem.hxx
+++ b/build2/filesystem.hxx
@@ -76,6 +76,9 @@ namespace build2
return rmfile (f, f, verbosity);
}
+ fs_status<rmfile_status>
+ rmsymlink (const path&, bool dir, uint16_t verbosity);
+
// Similar to rmfile() but for directories (note: not -r).
//
using rmdir_status = butl::rmdir_status;