diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/libstore/builtins/buildenv.cc | 87 |
2 files changed, 50 insertions, 39 deletions
diff --git a/configure.ac b/configure.ac index 7177c8914434..c41a83c97646 100644 --- a/configure.ac +++ b/configure.ac @@ -215,7 +215,7 @@ AC_SUBST(ENABLE_S3, [$enable_s3]) AC_LANG_POP(C++) if test -n "$enable_s3"; then - declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' ')) + declare -a aws_version_tokens=($(printf '#include <aws/core/VersionConfig.h>\nAWS_SDK_VERSION_STRING' | $CPP $CPPFLAGS - | grep -v '^#.*' | sed 's/"//g' | tr '.' ' ')) AC_DEFINE_UNQUOTED([AWS_VERSION_MAJOR], ${aws_version_tokens@<:@0@:>@}, [Major version of aws-sdk-cpp.]) AC_DEFINE_UNQUOTED([AWS_VERSION_MINOR], ${aws_version_tokens@<:@1@:>@}, [Minor version of aws-sdk-cpp.]) fi diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc index 938d02c35a02..74e706664694 100644 --- a/src/libstore/builtins/buildenv.cc +++ b/src/libstore/builtins/buildenv.cc @@ -9,14 +9,6 @@ namespace nix { typedef std::map<Path,int> Priorities; -static bool isDirectory(const Path & path) -{ - struct stat st; - if (stat(path.c_str(), &st) == -1) - throw SysError(format("getting status of '%1%'") % path); - return S_ISDIR(st.st_mode); -} - // FIXME: change into local variables. static Priorities priorities; @@ -26,14 +18,37 @@ static unsigned long symlinks; /* For each activated package, create symlinks */ static void createLinks(const Path & srcDir, const Path & dstDir, int priority) { - auto srcFiles = readDirectory(srcDir); + DirEntries srcFiles; + + try { + srcFiles = readDirectory(srcDir); + } catch (SysError & e) { + if (e.errNo == ENOTDIR) { + printError("warning: not including '%s' in the user environment because it's not a directory", srcDir); + return; + } + throw; + } + for (const auto & ent : srcFiles) { if (ent.name[0] == '.') /* not matched by glob */ continue; - const auto & srcFile = srcDir + "/" + ent.name; + auto srcFile = srcDir + "/" + ent.name; auto dstFile = dstDir + "/" + ent.name; + struct stat srcSt; + try { + if (stat(srcFile.c_str(), &srcSt) == -1) + throw SysError("getting status of '%1%'", srcFile); + } catch (SysError & e) { + if (e.errNo == ENOENT || e.errNo == ENOTDIR) { + printError("warning: skipping dangling symlink '%s'", dstFile); + continue; + } + throw; + } + /* The files below are special-cased to that they don't show up * in user profiles, either because they are useless, or * because they would cauase pointless collisions (e.g., each @@ -44,9 +59,10 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority) hasSuffix(srcFile, "/nix-support") || hasSuffix(srcFile, "/perllocal.pod") || hasSuffix(srcFile, "/info/dir") || - hasSuffix(srcFile, "/log")) { + hasSuffix(srcFile, "/log")) continue; - } else if (isDirectory(srcFile)) { + + else if (S_ISDIR(srcSt.st_mode)) { struct stat dstSt; auto res = lstat(dstFile.c_str(), &dstSt); if (res == 0) { @@ -54,10 +70,9 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority) createLinks(srcFile, dstFile, priority); continue; } else if (S_ISLNK(dstSt.st_mode)) { - auto target = readLink(dstFile); - if (!isDirectory(target)) - throw Error(format("collision between '%1%' and non-directory '%2%'") - % srcFile % target); + auto target = canonPath(dstFile, true); + if (!S_ISDIR(lstat(target).st_mode)) + throw Error("collision between '%1%' and non-directory '%2%'", srcFile, target); if (unlink(dstFile.c_str()) == -1) throw SysError(format("unlinking '%1%'") % dstFile); if (mkdir(dstFile.c_str(), 0755) == -1) @@ -68,28 +83,31 @@ static void createLinks(const Path & srcDir, const Path & dstDir, int priority) } } else if (errno != ENOENT) throw SysError(format("getting status of '%1%'") % dstFile); - } else { + } + + else { struct stat dstSt; auto res = lstat(dstFile.c_str(), &dstSt); if (res == 0) { if (S_ISLNK(dstSt.st_mode)) { - auto target = readLink(dstFile); auto prevPriority = priorities[dstFile]; if (prevPriority == priority) - throw Error(format( + throw Error( "packages '%1%' and '%2%' have the same priority %3%; " "use 'nix-env --set-flag priority NUMBER INSTALLED_PKGNAME' " "to change the priority of one of the conflicting packages" - " (0 being the highest priority)" - ) % srcFile % target % priority); + " (0 being the highest priority)", + srcFile, readLink(dstFile), priority); if (prevPriority < priority) continue; if (unlink(dstFile.c_str()) == -1) throw SysError(format("unlinking '%1%'") % dstFile); - } + } else if (S_ISDIR(dstSt.st_mode)) + throw Error("collision between non-directory '%1%' and directory '%2%'", srcFile, dstFile); } else if (errno != ENOENT) throw SysError(format("getting status of '%1%'") % dstFile); } + createSymlink(srcFile, dstFile); priorities[dstFile] = priority; symlinks++; @@ -105,24 +123,18 @@ static Path out; static void addPkg(const Path & pkgDir, int priority) { - if (done.find(pkgDir) != done.end()) - return; + if (done.count(pkgDir)) return; done.insert(pkgDir); createLinks(pkgDir, out, priority); - auto propagatedFN = pkgDir + "/nix-support/propagated-user-env-packages"; - std::string propagated; - { - AutoCloseFD fd = open(propagatedFN.c_str(), O_RDONLY | O_CLOEXEC); - if (!fd) { - if (errno == ENOENT) - return; - throw SysError(format("opening '%1%'") % propagatedFN); - } - propagated = readFile(fd.get()); + + try { + for (const auto & p : tokenizeString<std::vector<string>>( + readFile(pkgDir + "/nix-support/propagated-user-env-packages"), " \n")) + if (!done.count(p)) + postponed.insert(p); + } catch (SysError & e) { + if (e.errNo != ENOENT && e.errNo != ENOTDIR) throw; } - for (const auto & p : tokenizeString<std::vector<string>>(propagated, " \n")) - if (done.find(p) == done.end()) - postponed.insert(p); } struct Package { @@ -190,4 +202,3 @@ void builtinBuildenv(const BasicDerivation & drv) } } - |