diff options
author | 2016-12-21 15:01:36 +0000 | |
---|---|---|
committer | 2016-12-21 17:23:51 +0000 | |
commit | 7de9b6f1d9748d7347fa76f5ac8d0258c79b6d70 (patch) | |
tree | e0fc695c7e65e6d0fcd9f2929de6811afdf7e734 | |
parent | fd31061d4cd99277ba1cfacd17ac316f8dfea4f5 (diff) |
Bazel client, Windows: implement ReadFile
Implement blaze_util::ReadFile on top of the
::ReadFile Windows API function.
Also implement blaze_util::AsWindowsPath so we can
convert MSYS paths to Windows widechar paths.
Add tests.
See https://github.com/bazelbuild/bazel/issues/2107
--
PiperOrigin-RevId: 142659955
MOS_MIGRATED_REVID=142659955
-rw-r--r-- | src/main/cpp/util/file_posix.cc | 2 | ||||
-rw-r--r-- | src/main/cpp/util/file_windows.cc | 41 | ||||
-rw-r--r-- | src/test/cpp/util/file_test.cc | 24 |
3 files changed, 59 insertions, 8 deletions
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc index c5568a4c3e..127f811d32 100644 --- a/src/main/cpp/util/file_posix.cc +++ b/src/main/cpp/util/file_posix.cc @@ -179,7 +179,6 @@ pair<string, string> SplitPath(const string &path) { return std::make_pair(string(path, 0, pos), string(path, pos + 1)); } -#endif // not __CYGWIN__ bool ReadFile(const string &filename, string *content, int max_size) { int fd = open(filename.c_str(), O_RDONLY); @@ -190,6 +189,7 @@ bool ReadFile(const string &filename, string *content, int max_size) { close(fd); return result; } +#endif // not __CYGWIN__ bool WriteFile(const void *data, size_t size, const string &filename) { UnlinkPath(filename); // We don't care about the success of this. diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc index 78cb331185..6ded8c83cf 100644 --- a/src/main/cpp/util/file_windows.cc +++ b/src/main/cpp/util/file_windows.cc @@ -217,14 +217,43 @@ bool AsWindowsPath(const string& path, wstring* result) { return true; } -#ifdef COMPILER_MSVC bool ReadFile(const string& filename, string* content, int max_size) { - // TODO(bazel-team): implement this. - pdie(255, "blaze_util::ReadFile is not implemented on Windows"); - return false; + wstring wfilename; + if (!AsWindowsPath(filename, &wfilename)) { + // Failed to convert the path because it was an absolute MSYS path but we + // could not retrieve the BAZEL_SH envvar. + return false; + } + + if (wfilename.size() > MAX_PATH) { + // CreateFileW requires that paths longer than MAX_PATH be prefixed with + // "\\?\", so add that here. + // TODO(laszlocsomor): add a test for this code path. + wfilename = wstring(L"\\\\?\\") + wfilename; + } + + HANDLE handle = CreateFileW( + /* lpFileName */ wfilename.c_str(), + /* dwDesiredAccess */ GENERIC_READ, + /* dwShareMode */ FILE_SHARE_READ, + /* lpSecurityAttributes */ NULL, + /* dwCreationDisposition */ OPEN_EXISTING, + /* dwFlagsAndAttributes */ FILE_ATTRIBUTE_NORMAL, + /* hTemplateFile */ NULL); + if (handle == INVALID_HANDLE_VALUE) { + return false; + } + + bool result = ReadFrom( + [handle](void* buf, int len) { + DWORD actually_read = 0; + ::ReadFile(handle, buf, len, &actually_read, NULL); + return actually_read; + }, + content, max_size); + CloseHandle(handle); + return result; } -#else // not COMPILER_MSVC -#endif // COMPILER_MSVC #ifdef COMPILER_MSVC bool WriteFile(const void* data, size_t size, const string& filename) { diff --git a/src/test/cpp/util/file_test.cc b/src/test/cpp/util/file_test.cc index f98ed9975a..7c15ceb816 100644 --- a/src/test/cpp/util/file_test.cc +++ b/src/test/cpp/util/file_test.cc @@ -11,10 +11,11 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#include <stdio.h> #include <string.h> #include <memory> // unique_ptr -#include <thread> // NOLINT (to slience Google-internal linter) +#include <thread> // NOLINT (to silence Google-internal linter) #include "src/main/cpp/util/file.h" #include "src/main/cpp/util/file_platform.h" @@ -22,6 +23,8 @@ namespace blaze_util { +using std::string; + TEST(FileTest, TestNormalizePath) { ASSERT_EQ(string(""), NormalizePath("")); ASSERT_EQ(string(""), NormalizePath(".")); @@ -66,4 +69,23 @@ TEST(FileTest, TestMultiThreadedPipe) { ASSERT_EQ(0, strncmp(buffer, "hello world", 11)); } +TEST(FileTest, TestReadFile) { + const char* tempdir = getenv("TEST_TMPDIR"); + ASSERT_NE(nullptr, tempdir); + ASSERT_NE(0, tempdir[0]); + + std::string filename(JoinPath(tempdir, "test.readfile")); + FILE* fh = fopen(filename.c_str(), "wt"); + ASSERT_NE(nullptr, fh); + ASSERT_EQ(11, fwrite("hello world", 1, 11, fh)); + fclose(fh); + + std::string actual; + ASSERT_TRUE(ReadFile(filename, &actual)); + ASSERT_EQ(std::string("hello world"), actual); + + ASSERT_TRUE(ReadFile(filename, &actual, 5)); + ASSERT_EQ(std::string("hello"), actual); +} + } // namespace blaze_util |