about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/libstore/builtins/buildenv.cc87
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)
 }
 
 }
-