Hopefully fix EPERM on macOS
This commit is contained in:
parent
9a24ece122
commit
4ce8a3ed45
1 changed files with 40 additions and 32 deletions
|
@ -1675,6 +1675,33 @@ void DerivationGoal::tryLocalBuild() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void chmod_(const Path & path, mode_t mode)
|
||||||
|
{
|
||||||
|
if (chmod(path.c_str(), mode) == -1)
|
||||||
|
throw SysError("setting permissions on '%s'", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Move/rename path 'src' to 'dst'. Temporarily make 'src' writable if
|
||||||
|
it's a directory and we're not root (to be able to update the
|
||||||
|
directory's parent link ".."). */
|
||||||
|
static void movePath(const Path & src, const Path & dst)
|
||||||
|
{
|
||||||
|
auto st = lstat(src);
|
||||||
|
|
||||||
|
bool changePerm = (geteuid() && S_ISDIR(st.st_mode) && !(st.st_mode & S_IWUSR));
|
||||||
|
|
||||||
|
if (changePerm)
|
||||||
|
chmod_(src, st.st_mode | S_IWUSR);
|
||||||
|
|
||||||
|
if (rename(src.c_str(), dst.c_str()))
|
||||||
|
throw SysError("renaming '%1%' to '%2%'", src, dst);
|
||||||
|
|
||||||
|
if (changePerm)
|
||||||
|
chmod_(dst, st.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void replaceValidPath(const Path & storePath, const Path & tmpPath)
|
void replaceValidPath(const Path & storePath, const Path & tmpPath)
|
||||||
{
|
{
|
||||||
/* We can't atomically replace storePath (the original) with
|
/* We can't atomically replace storePath (the original) with
|
||||||
|
@ -1683,12 +1710,20 @@ void replaceValidPath(const Path & storePath, const Path & tmpPath)
|
||||||
we're repairing (say) Glibc, we end up with a broken system. */
|
we're repairing (say) Glibc, we end up with a broken system. */
|
||||||
Path oldPath = (format("%1%.old-%2%-%3%") % storePath % getpid() % random()).str();
|
Path oldPath = (format("%1%.old-%2%-%3%") % storePath % getpid() % random()).str();
|
||||||
if (pathExists(storePath))
|
if (pathExists(storePath))
|
||||||
rename(storePath.c_str(), oldPath.c_str());
|
movePath(storePath, oldPath);
|
||||||
if (rename(tmpPath.c_str(), storePath.c_str()) == -1) {
|
|
||||||
auto ex = SysError("moving '%s' to '%s'", tmpPath, storePath);
|
try {
|
||||||
rename(oldPath.c_str(), storePath.c_str()); // attempt to recover
|
movePath(tmpPath, storePath);
|
||||||
throw ex;
|
} catch (...) {
|
||||||
|
try {
|
||||||
|
// attempt to recover
|
||||||
|
movePath(oldPath, storePath);
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
}
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
deletePath(oldPath);
|
deletePath(oldPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2006,13 +2041,6 @@ HookReply DerivationGoal::tryBuildHook()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void chmod_(const Path & path, mode_t mode)
|
|
||||||
{
|
|
||||||
if (chmod(path.c_str(), mode) == -1)
|
|
||||||
throw SysError("setting permissions on '%s'", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int childEntry(void * arg)
|
int childEntry(void * arg)
|
||||||
{
|
{
|
||||||
((DerivationGoal *) arg)->runChild();
|
((DerivationGoal *) arg)->runChild();
|
||||||
|
@ -3731,26 +3759,6 @@ void DerivationGoal::runChild()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Move/rename path 'src' to 'dst'. Temporarily make 'src' writable if
|
|
||||||
it's a directory and we're not root (to be able to update the
|
|
||||||
directory's parent link ".."). */
|
|
||||||
static void movePath(const Path & src, const Path & dst)
|
|
||||||
{
|
|
||||||
auto st = lstat(src);
|
|
||||||
|
|
||||||
bool changePerm = (geteuid() && S_ISDIR(st.st_mode) && !(st.st_mode & S_IWUSR));
|
|
||||||
|
|
||||||
if (changePerm)
|
|
||||||
chmod_(src, st.st_mode | S_IWUSR);
|
|
||||||
|
|
||||||
if (rename(src.c_str(), dst.c_str()))
|
|
||||||
throw SysError("renaming '%1%' to '%2%'", src, dst);
|
|
||||||
|
|
||||||
if (changePerm)
|
|
||||||
chmod_(dst, st.st_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DerivationGoal::registerOutputs()
|
void DerivationGoal::registerOutputs()
|
||||||
{
|
{
|
||||||
/* When using a build hook, the build hook can register the output
|
/* When using a build hook, the build hook can register the output
|
||||||
|
|
Loading…
Reference in a new issue