From 8a82f67e2cb3366ab6988bcb56eb06c1d56fdc5d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 28 Apr 2018 18:04:08 +0200 Subject: Use rmsymlink() to portably remove symlinks --- build2/algorithm.cxx | 23 +++++++++++++++-------- build2/filesystem.cxx | 27 +++++++++++++++++++++++++++ build2/filesystem.hxx | 3 +++ 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 + 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 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 + rmsymlink (const path&, bool dir, uint16_t verbosity); + // Similar to rmfile() but for directories (note: not -r). // using rmdir_status = butl::rmdir_status; -- cgit v1.1