diff options
author | Laszlo Csomor <laszlocsomor@google.com> | 2017-01-20 10:05:18 +0000 |
---|---|---|
committer | Vladimir Moskva <vladmos@google.com> | 2017-01-20 12:21:39 +0000 |
commit | d5527469ca629f806a7576783289cc0613bf418b (patch) | |
tree | cc2716786b0e2f6092ba5515f9af997ef7a98705 /src/main/cpp/util | |
parent | 9a338502f625756a046301a98f209cae8ec675aa (diff) |
Bazel client, Windows: impl. ForEachDirectoryEntry
Implement ForEachDirectoryEntry on Windows using
FindFirstFileW / FindNextFileW.
Supports long paths and traversing junctions.
See https://github.com/bazelbuild/bazel/issues/2107
See https://github.com/bazelbuild/bazel/issues/2181
--
PiperOrigin-RevId: 145062749
MOS_MIGRATED_REVID=145062749
Diffstat (limited to 'src/main/cpp/util')
-rw-r--r-- | src/main/cpp/util/file_posix.cc | 2 | ||||
-rw-r--r-- | src/main/cpp/util/file_windows.cc | 33 |
2 files changed, 29 insertions, 6 deletions
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc index a1d806a9d9..c45eb3915c 100644 --- a/src/main/cpp/util/file_posix.cc +++ b/src/main/cpp/util/file_posix.cc @@ -364,7 +364,6 @@ string GetCwd() { bool ChangeDirectory(const string& path) { return chdir(path.c_str()) == 0; } -#endif // not __CYGWIN__ void ForEachDirectoryEntry(const string &path, DirectoryEntryConsumer *consume) { @@ -398,5 +397,6 @@ void ForEachDirectoryEntry(const string &path, closedir(dir); } +#endif // not __CYGWIN__ } // namespace blaze_util diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc index b1fadddf4a..bea092d9ff 100644 --- a/src/main/cpp/util/file_windows.cc +++ b/src/main/cpp/util/file_windows.cc @@ -993,14 +993,37 @@ bool ChangeDirectory(const string& path) { return true; } -#ifdef COMPILER_MSVC void ForEachDirectoryEntry(const string &path, DirectoryEntryConsumer *consume) { - // TODO(bazel-team): implement this. - pdie(255, "blaze_util::ForEachDirectoryEntry is not implemented on Windows"); + wstring wpath; + if (path.empty() || IsDevNull(path)) { + return; + } + if (!AsWindowsPath(path, &wpath)) { + pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, + "ForEachDirectoryEntry(%s): AsWindowsPath failed", path.c_str()); + } + + static const wstring kDot(L"."); + static const wstring kDotDot(L".."); + + wpath = L"\\\\?\\" + wpath + L"\\"; + WIN32_FIND_DATAW metadata; + windows_util::AutoHandle handle( + FindFirstFileW((wpath + L"*").c_str(), &metadata)); + if (handle.handle == INVALID_HANDLE_VALUE) { + return; // directory does not exist or is empty + } + + do { + if (kDot != metadata.cFileName && kDotDot != metadata.cFileName) { + wstring wname = wpath + metadata.cFileName; + string name(WstringToCstring(/* omit prefix */ 4 + wname.c_str()).get()); + bool is_dir = (metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + consume->Consume(name, is_dir); + } + } while (FindNextFileW(handle.handle, &metadata)); } -#else // not COMPILER_MSVC -#endif // COMPILER_MSVC string NormalizeWindowsPath(string path) { if (path.empty()) { |