From 7577d358959b5e1797f441a1f6cb8edf206cb179 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 11 Jul 2017 23:20:01 +0200 Subject: [PATCH] replaceSymlink(): Handle the case where the temporary file already exists Not really necessary anymore for #849, but still nice to have. (cherry picked from commit 2965d40612e16388ef2177d2a13d168848c6ca8a) --- src/libutil/util.cc | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 1d6c38d3..62d8efa3 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -431,12 +431,21 @@ void createSymlink(const Path & target, const Path & link) void replaceSymlink(const Path & target, const Path & link) { - Path tmp = canonPath(dirOf(link) + "/.new_" + baseNameOf(link)); + for (unsigned int n = 0; true; n++) { + Path tmp = canonPath(fmt("%s/.%d_%s", dirOf(link), n, baseNameOf(link))); - createSymlink(target, tmp); + try { + createSymlink(target, tmp); + } catch (SysError & e) { + if (e.errNo == EEXIST) continue; + throw; + } - if (rename(tmp.c_str(), link.c_str()) != 0) - throw SysError(format("renaming ‘%1%’ to ‘%2%’") % tmp % link); + if (rename(tmp.c_str(), link.c_str()) != 0) + throw SysError(format("renaming ‘%1%’ to ‘%2%’") % tmp % link); + + break; + } }