about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/primops.cc37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 0ec39f553c61..ca4ccf449599 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -800,6 +800,42 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
     mkPath(v, state.findFile(searchPath, path).c_str());
 }
 
+/* Read a directory (without . or ..) */
+static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+    PathSet ctx;
+    Path path = state.coerceToPath(pos, *args[0], ctx);
+    try {
+        realiseContext(ctx);
+    } catch (InvalidPathError & e) {
+        throw EvalError(format("cannot read ‘%1%’, since path ‘%2%’ is not valid, at %3%")
+            % path % e.path % pos);
+    }
+
+    DirEntries entries = readDirectory(path);
+    state.mkAttrs(v, entries.size());
+
+    for (const auto & ent : entries) {
+        Value * ent_val = state.allocAttr(v, state.symbols.create(ent.name));
+        if (ent.type == DT_UNKNOWN) {
+            struct stat st = lstat(path + "/" + ent.name);
+            mkString(*ent_val,
+                S_ISREG(st.st_mode) ? "regular" :
+                S_ISDIR(st.st_mode) ? "directory" :
+                S_ISLNK(st.st_mode) ? "symlink" :
+                "unknown");
+        } else {
+            mkString(*ent_val,
+                ent.type == DT_REG ? "regular" :
+                ent.type == DT_DIR ? "directory" :
+                ent.type == DT_LNK ? "symlink" :
+                "unknown");
+        }
+    }
+
+    v.attrs->sort();
+}
+
 
 /*************************************************************
  * Creating files
@@ -1460,6 +1496,7 @@ void EvalState::createBaseEnv()
     addPrimOp("baseNameOf", 1, prim_baseNameOf);
     addPrimOp("dirOf", 1, prim_dirOf);
     addPrimOp("__readFile", 1, prim_readFile);
+    addPrimOp("__readDir", 1, prim_readDir);
     addPrimOp("__findFile", 2, prim_findFile);
 
     // Creating files