From 27385b1acfbecb815862762337ba1cdde7237576 Mon Sep 17 00:00:00 2001 From: Loo Rong Jie Date: Wed, 8 Aug 2018 22:52:58 -0700 Subject: [singlejar] Port mapped_file for Windows `src/tools/singlejar/mapped_file_*.inc` are now included in `src/tools/singlejar/mapped_file.cc` instead of header file and no longer inline most member functions: these functions are too large for inlining. /cc @laszlocsomor Closes #5780. PiperOrigin-RevId: 207998444 --- src/tools/singlejar/BUILD | 8 ++- src/tools/singlejar/mapped_file.cc | 21 ++++++ src/tools/singlejar/mapped_file.h | 25 +++---- src/tools/singlejar/mapped_file_posix.inc | 8 +-- src/tools/singlejar/mapped_file_windows.inc | 101 +++++++++++++++++++++++----- src/tools/singlejar/output_jar.cc | 4 ++ 6 files changed, 129 insertions(+), 38 deletions(-) create mode 100644 src/tools/singlejar/mapped_file.cc (limited to 'src') diff --git a/src/tools/singlejar/BUILD b/src/tools/singlejar/BUILD index 01415cccbb..2f0164dd0e 100644 --- a/src/tools/singlejar/BUILD +++ b/src/tools/singlejar/BUILD @@ -24,6 +24,7 @@ filegroup( "diag.h", "input_jar.cc", "input_jar.h", + "mapped_file.cc", "mapped_file.h", "mapped_file_posix.inc", "mapped_file_windows.inc", @@ -348,13 +349,16 @@ cc_library( cc_library( name = "mapped_file", - srcs = select({ + srcs = ["mapped_file.cc"] + select({ "//src:windows": ["mapped_file_windows.inc"], "//conditions:default": ["mapped_file_posix.inc"], }), hdrs = ["mapped_file.h"], visibility = ["//visibility:private"], - deps = [":diag"], + deps = [ + ":diag", + ":port", + ], ) cc_library( diff --git a/src/tools/singlejar/mapped_file.cc b/src/tools/singlejar/mapped_file.cc new file mode 100644 index 0000000000..98aca74674 --- /dev/null +++ b/src/tools/singlejar/mapped_file.cc @@ -0,0 +1,21 @@ +// Copyright 2018 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// 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 "src/tools/singlejar/mapped_file.h" + +#ifdef _WIN32 +#include "src/tools/singlejar/mapped_file_windows.inc" +#else // not _WIN32 +#include "src/tools/singlejar/mapped_file_posix.inc" +#endif // _WIN32 diff --git a/src/tools/singlejar/mapped_file.h b/src/tools/singlejar/mapped_file.h index f4ada45a2b..bca19bc18d 100644 --- a/src/tools/singlejar/mapped_file.h +++ b/src/tools/singlejar/mapped_file.h @@ -17,6 +17,8 @@ #include +#include "src/tools/singlejar/port.h" + /* * A mapped read-only file with auto closing. * @@ -28,12 +30,6 @@ */ class MappedFile { public: -#ifdef _WIN32 - typedef /* HANDLE = void* */ void *FileHandleType; -#else // not _WIN32 - typedef int FileHandleType; -#endif // _WIN32 - MappedFile(); ~MappedFile() { Close(); } @@ -51,23 +47,20 @@ class MappedFile { const unsigned char *address(off_t offset) const { return mapped_start_ + offset; } - off_t offset(const void *address) const { + off64_t offset(const void *address) const { return reinterpret_cast(address) - mapped_start_; } - FileHandleType fd() const { return fd_; } + int fd() const { return fd_; } size_t size() const { return mapped_end_ - mapped_start_; } - bool is_open() const; + bool is_open() const { return fd_ >= 0; } private: unsigned char *mapped_start_; unsigned char *mapped_end_; - FileHandleType fd_; -}; - + int fd_; #ifdef _WIN32 -#include "src/tools/singlejar/mapped_file_windows.inc" -#else // not _WIN32 -#include "src/tools/singlejar/mapped_file_posix.inc" -#endif // _WIN32 + /* HANDLE */ void *hMapFile_; +#endif +}; #endif // BAZEL_SRC_TOOLS_SINGLEJAR_MAPPED_FILE_H_ diff --git a/src/tools/singlejar/mapped_file_posix.inc b/src/tools/singlejar/mapped_file_posix.inc index ad6c6a5310..637661b719 100644 --- a/src/tools/singlejar/mapped_file_posix.inc +++ b/src/tools/singlejar/mapped_file_posix.inc @@ -30,10 +30,10 @@ #error This code for 64 bit Unix. #endif -inline MappedFile::MappedFile() +MappedFile::MappedFile() : mapped_start_(nullptr), mapped_end_(nullptr), fd_(-1) {} -inline bool MappedFile::Open(const std::string& path) { +bool MappedFile::Open(const std::string& path) { if (is_open()) { diag_errx(1, "%s:%d: This instance is already open", __FILE__, __LINE__); } @@ -60,7 +60,7 @@ inline bool MappedFile::Open(const std::string& path) { return true; } -inline void MappedFile::Close() { +void MappedFile::Close() { if (is_open()) { munmap(mapped_start_, mapped_end_ - mapped_start_); mapped_start_ = mapped_end_ = nullptr; @@ -69,6 +69,4 @@ inline void MappedFile::Close() { } } -inline bool MappedFile::is_open() const { return fd_ >= 0; } - #endif // BAZEL_SRC_TOOLS_SINGLEJAR_MAPPED_FILE_POSIX_H_ diff --git a/src/tools/singlejar/mapped_file_windows.inc b/src/tools/singlejar/mapped_file_windows.inc index 366103f57a..43e524ae12 100644 --- a/src/tools/singlejar/mapped_file_windows.inc +++ b/src/tools/singlejar/mapped_file_windows.inc @@ -19,30 +19,101 @@ #error This code is for 64 bit Windows. #endif +#include "src/tools/singlejar/diag.h" + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + #include #include -typedef HANDLE FileHandleType; +MappedFile::MappedFile() + : mapped_start_(nullptr), + mapped_end_(nullptr), + fd_(-1), + hMapFile_(INVALID_HANDLE_VALUE) {} -inline MappedFile::MappedFile() - : mapped_start_(nullptr), mapped_end_(nullptr), fd_(INVALID_HANDLE_VALUE) {} +bool MappedFile::Open(const std::string& path) { + if (is_open()) { + diag_errx(1, "%s:%d: This instance is already open", __FILE__, __LINE__); + } + if ((fd_ = _open(path.c_str(), O_RDONLY | O_BINARY)) < 0) { + diag_warn("%s:%d: open %s:", __FILE__, __LINE__, path.c_str()); + return false; + } -inline bool MappedFile::Open(const std::string& path) { - // TODO(laszlocsomor): implement as part of - // https://github.com/bazelbuild/bazel/issues/2241 - return false; -} + HANDLE hFile = reinterpret_cast(_get_osfhandle(fd_)); + LARGE_INTEGER temp; + ::GetFileSizeEx(hFile, &temp); + size_t fileSize = temp.QuadPart; + + if (fileSize == 0) { + // This is where Windows implementation differs from POSIX's. + // CreateFileMapping cannot map empty file: + // + // From + // https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createfilemappinga + // + // An attempt to map a file with a length of 0 (zero) fails with an error + // code of ERROR_FILE_INVALID. Applications should test for files with a + // length of 0 (zero) and reject those files. + // + // Since the test at //src/tools/singlerjar/input_jar_bad_jar_test expects + // empty file to fail anyway, returning error here shouldn't be a problem. + diag_warn("%s:%d: Windows MappedFile cannot handle empty file (%s)", + __FILE__, __LINE__, path.c_str()); + _close(fd_); + fd_ = -1; + return false; + } + + hMapFile_ = ::CreateFileMapping( + hFile, + nullptr, // default security + PAGE_READONLY, // read-only permission + static_cast(fileSize >> 32), // size of mapping object, high + static_cast(fileSize), // size of mapping object, low + nullptr); // name of mapping object + + if (hMapFile_ == nullptr) { + diag_warn("%s:%d: CreateFileMapping for %s failed", __FILE__, __LINE__, + path.c_str()); + _close(fd_); + fd_ = -1; + return false; + } + + mapped_start_ = static_cast( + MapViewOfFile(hMapFile_, + FILE_MAP_READ | FILE_MAP_COPY, // PROT_READ | MAP_PRIVATE + 0, // file offset, high + 0, // file offset, low + fileSize)); // file size + if (mapped_start_ == nullptr) { + diag_warn("%s:%d: MapViewOfFile for %s failed", __FILE__, __LINE__, + path.c_str()); + ::CloseHandle(hMapFile_); + _close(fd_); + hMapFile_ = INVALID_HANDLE_VALUE; + fd_ = -1; + return false; + } -inline void MappedFile::Close() { - // TODO(laszlocsomor): implement as part of - // https://github.com/bazelbuild/bazel/issues/2241 + mapped_end_ = mapped_start_ + fileSize; + return true; } -inline bool MappedFile::is_open() const { - // TODO(laszlocsomor): implement as part of - // https://github.com/bazelbuild/bazel/issues/2241 - return false; +void MappedFile::Close() { + if (is_open()) { + ::UnmapViewOfFile(mapped_start_); + ::CloseHandle(hMapFile_); + _close(fd_); + hMapFile_ = INVALID_HANDLE_VALUE; + fd_ = -1; + mapped_start_ = mapped_end_ = nullptr; + } } #endif // BAZEL_SRC_TOOLS_SINGLEJAR_MAPPED_FILE_WINDOWS_H_ \ No newline at end of file diff --git a/src/tools/singlejar/output_jar.cc b/src/tools/singlejar/output_jar.cc index 5b6d24fc6b..923894698d 100644 --- a/src/tools/singlejar/output_jar.cc +++ b/src/tools/singlejar/output_jar.cc @@ -24,6 +24,10 @@ #include #include +#ifndef _WIN32 +#include +#endif + #include "src/tools/singlejar/combiners.h" #include "src/tools/singlejar/diag.h" #include "src/tools/singlejar/input_jar.h" -- cgit v1.2.3