diff --git a/source/vibe/core/file.d b/source/vibe/core/file.d index 830cc52..a69b861 100644 --- a/source/vibe/core/file.d +++ b/source/vibe/core/file.d @@ -515,11 +515,13 @@ enum FileMode { enum DirectoryListMode { /// Only iterate the directory itself - shallow, + shallow = 0, + /// Only iterate over directories directly within the given directory + shallowDirectories = 1<<1, /// Iterate recursively (depth-first, pre-order) - recursive, + recursive = 1<<0, /// Iterate only directories recursively (depth-first, pre-order) - recursiveDirectories, + recursiveDirectories = recursive | shallowDirectories, } @@ -948,7 +950,8 @@ private void performListDirectory(ListDirectoryRequest req) @trusted nothrow { scope (exit) req.channel.close(); - auto dirs_only = req.spanMode == DirectoryListMode.recursiveDirectories; + auto dirs_only = !!(req.spanMode & DirectoryListMode.shallowDirectories); + auto rec = !!(req.spanMode & DirectoryListMode.recursive); bool scanRec(NativePath path) { @@ -1001,7 +1004,7 @@ private void performListDirectory(ListDirectoryRequest req) try req.channel.put(ListDirectoryData(fi, null)); catch (Exception e) return false; // channel got closed - if (req.spanMode != DirectoryListMode.shallow && fi.isDirectory) { + if (rec && fi.isDirectory) { if (fi.isSymlink && !req.followSymlinks) continue; try { @@ -1030,29 +1033,28 @@ private void performListDirectory(ListDirectoryRequest req) continue; FileInfo fi; - auto zi = de.d_name[].countUntil(0); + auto zi = de.d_name[].representation.countUntil(0); if (zi < 0) zi = de.d_name.length; if (de.d_name[0 .. zi].among(".", "..")) continue; fi.name = de.d_name[0 .. zi].idup; fi.directory = path; + fi.hidden = de.d_name[0] == '.'; stat_t st; - if (fstatat(dfd, fi.name.toStringz, &st, AT_SYMLINK_NOFOLLOW) != 0) - continue; + if (fstatat(dfd, fi.name.toStringz, &st, AT_SYMLINK_NOFOLLOW) == 0) { + fi.isSymlink = S_ISLNK(st.st_mode); - fi.isSymlink = S_ISLNK(st.st_mode); + // apart from the symlink flag, get the rest of the information from the link target + if (fi.isSymlink) fstatat(dfd, fi.name.toStringz, &st, 0); - // apart from the symlink flag, get the rest of the information from the link target - if (fi.isSymlink) fstatat(dfd, fi.name.toStringz, &st, 0); - - fi.size = st.st_size; - fi.timeModified = timebase + st.st_mtime.seconds + (st.st_mtimensec / 100).hnsecs; - fi.timeCreated = timebase + st.st_ctime.seconds + (st.st_ctimensec / 100).hnsecs; - fi.isDirectory = S_ISDIR(st.st_mode); - fi.isFile = S_ISREG(st.st_mode); - fi.hidden = de.d_name[0] == '.'; + fi.size = st.st_size; + fi.timeModified = timebase + st.st_mtime.seconds + (st.st_mtimensec / 100).hnsecs; + fi.timeCreated = timebase + st.st_ctime.seconds + (st.st_ctimensec / 100).hnsecs; + fi.isDirectory = S_ISDIR(st.st_mode); + fi.isFile = S_ISREG(st.st_mode); + } // skip non-directories if requested if (dirs_only && !fi.isDirectory) @@ -1061,7 +1063,7 @@ private void performListDirectory(ListDirectoryRequest req) try req.channel.put(ListDirectoryData(fi, null)); catch (Exception e) return false; // channel got closed - if (req.spanMode != DirectoryListMode.shallow && fi.isDirectory) { + if (rec && fi.isDirectory) { if (fi.isSymlink && !req.followSymlinks) continue; try { @@ -1089,8 +1091,12 @@ version (Posix) { extern(C) @safe nothrow @nogc { static if (!is(typeof(dirfd))) int dirfd(DIR*); - static if (!is(typeof(fstatat))) - int fstatat(int dirfd, const(char)* pathname, stat_t *statbuf, int flags); + static if (!is(typeof(fstatat))) { + version (OSX) { + pragma(mangle, "fstatat$INODE64") + int fstatat(int dirfd, const(char)* pathname, stat_t *statbuf, int flags); + } else int fstatat(int dirfd, const(char)* pathname, stat_t *statbuf, int flags); + } } version (darwin) { diff --git a/source/vibe/core/task.d b/source/vibe/core/task.d index 745ad24..0698ae3 100644 --- a/source/vibe/core/task.d +++ b/source/vibe/core/task.d @@ -440,7 +440,7 @@ final package class TaskFiber : Fiber { debug if (ms_taskEventCallback) ms_taskEventCallback(TaskEvent.end, handle); debug if (() @trusted { return (cast(shared)this); } ().getTaskStatus().interrupt) - logDebug("Task exited while an interrupt was in flight."); + logDebugV("Task exited while an interrupt was in flight."); } catch (Exception e) { debug if (ms_taskEventCallback) ms_taskEventCallback(TaskEvent.fail, handle); e.logException!(LogLevel.critical)("Task terminated with uncaught exception"); diff --git a/tests/vibe.core.file.d b/tests/vibe.core.file.d index 1da05fa..8452c38 100644 --- a/tests/vibe.core.file.d +++ b/tests/vibe.core.file.d @@ -11,7 +11,7 @@ enum ubyte[] bytes(BYTES...) = [BYTES]; void main() { - auto f = openFile("test.dat", FileMode.createTrunc); + auto f = openFile("têst.dat", FileMode.createTrunc); assert(f.size == 0); assert(f.tell == 0); f.write(bytes!(1, 2, 3, 4, 5)); @@ -33,8 +33,8 @@ void main() assert(dst[] == bytes!(3, 4, 5, 6, 7)); f.close(); - auto fi = getFileInfo("test.dat"); - assert(fi.name == "test.dat"); + auto fi = getFileInfo("têst.dat"); + assert(fi.name == "têst.dat"); assert(fi.isFile); assert(!fi.isDirectory); assert(!fi.isSymlink); @@ -43,5 +43,18 @@ void main() assertThrown(getFileInfo("*impossible:file?")); - removeFile("test.dat"); + bool found = false; + listDirectory(".", (fi) { + if (fi.name != "têst.dat") return true; + assert(fi.isFile); + assert(!fi.isDirectory); + assert(!fi.isSymlink); + assert(!fi.hidden); + assert(fi.size == 10); + found = true; + return true; + }); + assert(found, "listDirectory did not find test file."); + + removeFile("têst.dat"); }