* Resolve all symlink components in the location of the temporary
build directory (TMPDIR, i.e., /tmp). Fixes NIX-26.
This commit is contained in:
parent
0f8d3c871b
commit
04be39734f
2 changed files with 25 additions and 4 deletions
|
@ -53,7 +53,7 @@ Path absPath(Path path, Path dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path canonPath(const Path & path)
|
Path canonPath(const Path & path, bool resolveSymlinks)
|
||||||
{
|
{
|
||||||
string s;
|
string s;
|
||||||
|
|
||||||
|
@ -61,6 +61,11 @@ Path canonPath(const Path & path)
|
||||||
throw Error(format("not an absolute path: `%1%'") % path);
|
throw Error(format("not an absolute path: `%1%'") % path);
|
||||||
|
|
||||||
string::const_iterator i = path.begin(), end = path.end();
|
string::const_iterator i = path.begin(), end = path.end();
|
||||||
|
string temp;
|
||||||
|
|
||||||
|
/* Count the number of times we follow a symlink and stop at some
|
||||||
|
arbitrary (but high) limit to prevent infinite loops. */
|
||||||
|
unsigned int followCount = 0, maxFollow = 1024;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
@ -84,6 +89,20 @@ Path canonPath(const Path & path)
|
||||||
else {
|
else {
|
||||||
s += '/';
|
s += '/';
|
||||||
while (i != end && *i != '/') s += *i++;
|
while (i != end && *i != '/') s += *i++;
|
||||||
|
|
||||||
|
/* If s points to a symlink, resolve it and restart (since
|
||||||
|
the symlink target might contain new symlinks). */
|
||||||
|
if (resolveSymlinks && isLink(s)) {
|
||||||
|
followCount++;
|
||||||
|
if (followCount >= maxFollow)
|
||||||
|
throw Error(format("infinite symlink recursion in path `%1%'") % path);
|
||||||
|
temp = absPath(readLink(s), dirOf(s))
|
||||||
|
+ string(i, end);
|
||||||
|
i = temp.begin(); /* restart */
|
||||||
|
end = temp.end();
|
||||||
|
s = "";
|
||||||
|
/* !!! potential for infinite loop */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +283,7 @@ void makePathReadOnly(const Path & path)
|
||||||
static Path tempName()
|
static Path tempName()
|
||||||
{
|
{
|
||||||
static int counter = 0;
|
static int counter = 0;
|
||||||
Path tmpRoot = canonPath(getEnv("TMPDIR", "/tmp"));
|
Path tmpRoot = canonPath(getEnv("TMPDIR", "/tmp"), true);
|
||||||
return (format("%1%/nix-%2%-%3%") % tmpRoot % getpid() % counter++).str();
|
return (format("%1%/nix-%2%-%3%") % tmpRoot % getpid() % counter++).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,10 @@ string getEnv(const string & key, const string & def = "");
|
||||||
Path absPath(Path path, Path dir = "");
|
Path absPath(Path path, Path dir = "");
|
||||||
|
|
||||||
/* Canonicalise a path by removing all `.' or `..' components and
|
/* Canonicalise a path by removing all `.' or `..' components and
|
||||||
double or trailing slashes. */
|
double or trailing slashes. Optionally resolves all symlink
|
||||||
Path canonPath(const Path & path);
|
components such that each component of the resulting path is *not*
|
||||||
|
a symbolic link. */
|
||||||
|
Path canonPath(const Path & path, bool resolveSymlinks = false);
|
||||||
|
|
||||||
/* Return the directory part of the given canonical path, i.e.,
|
/* Return the directory part of the given canonical path, i.e.,
|
||||||
everything before the final `/'. If the path is the root or an
|
everything before the final `/'. If the path is the root or an
|
||||||
|
|
Loading…
Reference in a new issue