From df03416eeac0d4838d69dde4d87373bc368f5d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 12 Jan 2021 17:21:48 +0100 Subject: [PATCH 1/5] Reduce visibility of minor debug log message. --- source/vibe/core/task.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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"); From d1273ca08b85b9366b54d801b32ef804fd32f2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 12 Jan 2021 17:23:07 +0100 Subject: [PATCH 2/5] Fix the declaration of fstatat on macOS. Was referencing the classic declaration that doesn't fit the current stat struct, leading to wrong stat results. --- source/vibe/core/file.d | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/vibe/core/file.d b/source/vibe/core/file.d index 830cc52..1acfded 100644 --- a/source/vibe/core/file.d +++ b/source/vibe/core/file.d @@ -1089,8 +1089,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) { From ca1fe414218fc3880d1ac02f5ffcfe0225fa4eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 12 Jan 2021 17:24:28 +0100 Subject: [PATCH 3/5] Add DirectoryListMode.shallowDirectories. Shallow iteration, returning only directories. DirectoryListMode is now defined using bit combinations for "recursive" and "directories-only". --- source/vibe/core/file.d | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/source/vibe/core/file.d b/source/vibe/core/file.d index 1acfded..cd0b55b 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 { @@ -1037,22 +1040,21 @@ private void performListDirectory(ListDirectoryRequest req) 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 { From 5e6231c738e06052becded238920b24941cdb6f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 12 Jan 2021 17:38:32 +0100 Subject: [PATCH 4/5] Fix zero byte index computation. --- source/vibe/core/file.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/vibe/core/file.d b/source/vibe/core/file.d index cd0b55b..a69b861 100644 --- a/source/vibe/core/file.d +++ b/source/vibe/core/file.d @@ -1033,7 +1033,7 @@ 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; From 874e56ccac8f7eb22a43e7091a40a530b6eb8d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 12 Jan 2021 17:42:32 +0100 Subject: [PATCH 5/5] Add a basic sanity check test for listDirectory and test extended UTF-8 characters. --- tests/vibe.core.file.d | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) 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"); }