Allow hard links between the outputs of a derivation

This commit is contained in:
Eelco Dolstra 2013-06-13 17:29:56 +02:00
parent cd49ee0897
commit 1b6ee8f4c7
3 changed files with 20 additions and 9 deletions

View file

@ -844,6 +844,11 @@ private:
bool repair; bool repair;
map<Path, Path> redirectedBadOutputs; map<Path, Path> redirectedBadOutputs;
/* Set of inodes seen during calls to canonicalisePathMetaData()
for this build's outputs. This needs to be shared between
outputs to allow hard links between outputs. */
InodesSeen inodesSeen;
/* Magic exit code denoting that setting up the child environment /* Magic exit code denoting that setting up the child environment
failed. (It's possible that the child actually returns the failed. (It's possible that the child actually returns the
exit code, but ah well.) */ exit code, but ah well.) */
@ -1493,7 +1498,7 @@ void DerivationGoal::buildDone()
/* Canonicalise first. This ensures that the path /* Canonicalise first. This ensures that the path
we're rewriting doesn't contain a hard link to we're rewriting doesn't contain a hard link to
/etc/shadow or something like that. */ /etc/shadow or something like that. */
canonicalisePathMetaData(path, buildUser.enabled() ? buildUser.getUID() : -1); canonicalisePathMetaData(path, buildUser.enabled() ? buildUser.getUID() : -1, inodesSeen);
/* FIXME: this is in-memory. */ /* FIXME: this is in-memory. */
StringSink sink; StringSink sink;
@ -2307,7 +2312,7 @@ void DerivationGoal::computeClosure()
/* Get rid of all weird permissions. This also checks that /* Get rid of all weird permissions. This also checks that
all files are owned by the build user, if applicable. */ all files are owned by the build user, if applicable. */
canonicalisePathMetaData(path, canonicalisePathMetaData(path,
buildUser.enabled() && rewrittenPaths.find(path) == rewrittenPaths.end() ? buildUser.getUID() : -1); buildUser.enabled() && rewrittenPaths.find(path) == rewrittenPaths.end() ? buildUser.getUID() : -1, inodesSeen);
/* For this output path, find the references to other paths /* For this output path, find the references to other paths
contained in it. Compute the SHA-256 NAR hash at the same contained in it. Compute the SHA-256 NAR hash at the same

View file

@ -500,10 +500,6 @@ void canonicaliseTimestampAndPermissions(const Path & path)
} }
typedef std::pair<dev_t, ino_t> Inode;
typedef set<Inode> InodesSeen;
static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSeen & inodesSeen) static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSeen & inodesSeen)
{ {
checkInterrupt(); checkInterrupt();
@ -561,10 +557,8 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
} }
void canonicalisePathMetaData(const Path & path, uid_t fromUid) void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & inodesSeen)
{ {
InodesSeen inodesSeen;
canonicalisePathMetaData_(path, fromUid, inodesSeen); canonicalisePathMetaData_(path, fromUid, inodesSeen);
/* On platforms that don't have lchown(), the top-level path can't /* On platforms that don't have lchown(), the top-level path can't
@ -580,6 +574,13 @@ void canonicalisePathMetaData(const Path & path, uid_t fromUid)
} }
void canonicalisePathMetaData(const Path & path, uid_t fromUid)
{
InodesSeen inodesSeen;
canonicalisePathMetaData(path, fromUid, inodesSeen);
}
void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & drv) void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation & drv)
{ {
string drvName = storePathToName(drvPath); string drvName = storePathToName(drvPath);

View file

@ -305,6 +305,10 @@ private:
}; };
typedef std::pair<dev_t, ino_t> Inode;
typedef set<Inode> InodesSeen;
/* "Fix", or canonicalise, the meta-data of the files in a store path /* "Fix", or canonicalise, the meta-data of the files in a store path
after it has been built. In particular: after it has been built. In particular:
- the last modification date on each file is set to 1 (i.e., - the last modification date on each file is set to 1 (i.e.,
@ -313,6 +317,7 @@ private:
without execute permission; setuid bits etc. are cleared) without execute permission; setuid bits etc. are cleared)
- the owner and group are set to the Nix user and group, if we're - the owner and group are set to the Nix user and group, if we're
in a setuid Nix installation. */ in a setuid Nix installation. */
void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & inodesSeen);
void canonicalisePathMetaData(const Path & path, uid_t fromUid); void canonicalisePathMetaData(const Path & path, uid_t fromUid);
void canonicaliseTimestampAndPermissions(const Path & path); void canonicaliseTimestampAndPermissions(const Path & path);