| Index: third_party/ijar/mapped_file_windows.cc
|
| diff --git a/third_party/ijar/mapped_file_windows.cc b/third_party/ijar/mapped_file_windows.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3a928c5191e67d62b3056760af91036f05309a04
|
| --- /dev/null
|
| +++ b/third_party/ijar/mapped_file_windows.cc
|
| @@ -0,0 +1,216 @@
|
| +// Copyright 2015 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 <stdio.h>
|
| +#include <windows.h>
|
| +#include <sys/cygwin.h>
|
| +
|
| +#include "third_party/ijar/mapped_file.h"
|
| +
|
| +#define MAX_ERROR 2048
|
| +
|
| +namespace devtools_ijar {
|
| +
|
| +static char errmsg[MAX_ERROR] = "";
|
| +
|
| +void PrintLastError(const char* op) {
|
| + char *message;
|
| + DWORD err = GetLastError();
|
| + FormatMessage(
|
| + FORMAT_MESSAGE_ALLOCATE_BUFFER
|
| + | FORMAT_MESSAGE_FROM_SYSTEM
|
| + | FORMAT_MESSAGE_IGNORE_INSERTS,
|
| + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
| + reinterpret_cast<char *>(&message),
|
| + 0, NULL);
|
| + snprintf(errmsg, MAX_ERROR, "%s: %s", op, message);
|
| + LocalFree(message);
|
| +}
|
| +
|
| +char* ToUnicodePath(const char* path) {
|
| + // Add \\?\ as prefix to enable unicode path which allows path length longer
|
| + // than 260
|
| + int length = strlen(path) + 5;
|
| + char* unicode_path = reinterpret_cast<char*>(malloc(length));
|
| + snprintf(unicode_path, length, "\\\\?\\%s", path);
|
| + return unicode_path;
|
| +}
|
| +
|
| +struct MappedInputFileImpl {
|
| + HANDLE file_;
|
| + HANDLE mapping_;
|
| +
|
| + MappedInputFileImpl(HANDLE file, HANDLE mapping) {
|
| + file_ = file;
|
| + mapping_ = mapping;
|
| + }
|
| +};
|
| +
|
| +MappedInputFile::MappedInputFile(const char* name) {
|
| + impl_ = NULL;
|
| + opened_ = false;
|
| + errmsg_ = errmsg;
|
| +
|
| + char* path = reinterpret_cast<char*>(
|
| + cygwin_create_path(CCP_POSIX_TO_WIN_A, name));
|
| + char* unicode_path = ToUnicodePath(path);
|
| + free(path);
|
| + HANDLE file = CreateFile(unicode_path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
| + OPEN_EXISTING, 0, NULL);
|
| + free(unicode_path);
|
| + if (file == INVALID_HANDLE_VALUE) {
|
| + PrintLastError("CreateFile()");
|
| + return;
|
| + }
|
| +
|
| + LARGE_INTEGER size;
|
| + if (!GetFileSizeEx(file, &size)) {
|
| + PrintLastError("GetFileSizeEx()");
|
| + CloseHandle(file);
|
| + return;
|
| + }
|
| +
|
| + HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY,
|
| + size.HighPart, size.LowPart, NULL);
|
| + if (mapping == NULL) {
|
| + PrintLastError("CreateFileMapping()");
|
| + CloseHandle(file);
|
| + return;
|
| + }
|
| +
|
| + void *view = MapViewOfFileEx(mapping, FILE_MAP_READ, 0, 0, 0, NULL);
|
| + if (view == NULL) {
|
| + PrintLastError("MapViewOfFileEx()");
|
| + CloseHandle(mapping);
|
| + CloseHandle(file);
|
| + return;
|
| + }
|
| +
|
| + impl_ = new MappedInputFileImpl(file, mapping);
|
| + length_ = size.QuadPart;
|
| + buffer_ = reinterpret_cast<u1*>(view);
|
| + opened_ = true;
|
| +}
|
| +
|
| +MappedInputFile::~MappedInputFile() {
|
| + delete impl_;
|
| +}
|
| +
|
| +void MappedInputFile::Discard(size_t bytes) {
|
| + // This is not supported on Windows for now. I'm not sure if we can unmap
|
| + // parts of an existing view and that this is necessary for Windows at all.
|
| + // At any rate, this only matters for >2GB (or maybe >4GB?) input files.
|
| +}
|
| +
|
| +int MappedInputFile::Close() {
|
| + if (!UnmapViewOfFile(buffer_)) {
|
| + PrintLastError("UnmapViewOfFile()");
|
| + return -1;
|
| + }
|
| +
|
| + if (!CloseHandle(impl_->mapping_)) {
|
| + PrintLastError("CloseHandle(mapping)");
|
| + return -1;
|
| + }
|
| +
|
| + if (!CloseHandle(impl_->file_)) {
|
| + PrintLastError("CloseHandle(file)");
|
| + return -1;
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +struct MappedOutputFileImpl {
|
| + HANDLE file_;
|
| + HANDLE mapping_;
|
| +
|
| + MappedOutputFileImpl(HANDLE file, HANDLE mapping) {
|
| + file_ = file;
|
| + mapping_ = mapping;
|
| + }
|
| +};
|
| +
|
| +MappedOutputFile::MappedOutputFile(const char* name, u8 estimated_size) {
|
| + impl_ = NULL;
|
| + opened_ = false;
|
| + errmsg_ = errmsg;
|
| +
|
| + char* path = reinterpret_cast<char*>(
|
| + cygwin_create_path(CCP_POSIX_TO_WIN_A, name));
|
| + char* unicode_path = ToUnicodePath(path);
|
| + free(path);
|
| + HANDLE file = CreateFile(unicode_path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
| + CREATE_ALWAYS, 0, NULL);
|
| + free(unicode_path);
|
| + if (file == INVALID_HANDLE_VALUE) {
|
| + PrintLastError("CreateFile()");
|
| + return;
|
| + }
|
| +
|
| + HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READWRITE,
|
| + estimated_size >> 32, estimated_size & 0xffffffffUL, NULL);
|
| + if (mapping == NULL) {
|
| + PrintLastError("CreateFileMapping()");
|
| + CloseHandle(file);
|
| + return;
|
| + }
|
| +
|
| + void *view = MapViewOfFileEx(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
|
| + if (view == NULL) {
|
| + PrintLastError("MapViewOfFileEx()");
|
| + CloseHandle(mapping);
|
| + CloseHandle(file);
|
| + return;
|
| + }
|
| +
|
| + impl_ = new MappedOutputFileImpl(file, mapping);
|
| + buffer_ = reinterpret_cast<u1*>(view);
|
| + opened_ = true;
|
| +}
|
| +
|
| +MappedOutputFile::~MappedOutputFile() {
|
| + delete impl_;
|
| +}
|
| +
|
| +int MappedOutputFile::Close(int size) {
|
| + if (!UnmapViewOfFile(buffer_)) {
|
| + PrintLastError("UnmapViewOfFile()");
|
| + return -1;
|
| + }
|
| +
|
| + if (!CloseHandle(impl_->mapping_)) {
|
| + PrintLastError("CloseHandle(mapping)");
|
| + return -1;
|
| + }
|
| +
|
| + if (!SetFilePointer(impl_->file_, size, NULL, FILE_BEGIN)) {
|
| + PrintLastError("SetFilePointer()");
|
| + return -1;
|
| + }
|
| +
|
| + if (!SetEndOfFile(impl_->file_)) {
|
| + PrintLastError("SetEndOfFile()");
|
| + return -1;
|
| + }
|
| +
|
| + if (!CloseHandle(impl_->file_)) {
|
| + PrintLastError("CloseHandle(file)");
|
| + return -1;
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +} // namespace devtools_ijar
|
|
|