diff options
Diffstat (limited to 'base/files')
-rw-r--r-- | base/files/memory_mapped_file.cc | 58 | ||||
-rw-r--r-- | base/files/memory_mapped_file.h | 76 | ||||
-rw-r--r-- | base/files/memory_mapped_file_posix.cc | 54 | ||||
-rw-r--r-- | base/files/memory_mapped_file_win.cc | 87 |
4 files changed, 275 insertions, 0 deletions
diff --git a/base/files/memory_mapped_file.cc b/base/files/memory_mapped_file.cc new file mode 100644 index 0000000..9e98bc6 --- /dev/null +++ b/base/files/memory_mapped_file.cc @@ -0,0 +1,58 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/memory_mapped_file.h" + +#include "base/file_path.h" +#include "base/logging.h" + +namespace base { + +MemoryMappedFile::~MemoryMappedFile() { + CloseHandles(); +} + +bool MemoryMappedFile::Initialize(const FilePath& file_name) { + if (IsValid()) + return false; + + if (!MapFileToMemory(file_name)) { + CloseHandles(); + return false; + } + + return true; +} + +bool MemoryMappedFile::Initialize(PlatformFile file) { + if (IsValid()) + return false; + + file_ = file; + + if (!MapFileToMemoryInternal()) { + CloseHandles(); + return false; + } + + return true; +} + +bool MemoryMappedFile::IsValid() const { + return data_ != NULL; +} + +bool MemoryMappedFile::MapFileToMemory(const FilePath& file_name) { + file_ = CreatePlatformFile(file_name, PLATFORM_FILE_OPEN | PLATFORM_FILE_READ, + NULL, NULL); + + if (file_ == kInvalidPlatformFileValue) { + DLOG(ERROR) << "Couldn't open " << file_name.AsUTF8Unsafe(); + return false; + } + + return MapFileToMemoryInternal(); +} + +} // namespace base diff --git a/base/files/memory_mapped_file.h b/base/files/memory_mapped_file.h new file mode 100644 index 0000000..6df1bad --- /dev/null +++ b/base/files/memory_mapped_file.h @@ -0,0 +1,76 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_FILES_MEMORY_MAPPED_FILE_H_ +#define BASE_FILES_MEMORY_MAPPED_FILE_H_ + +#include "base/base_export.h" +#include "base/basictypes.h" +#include "base/platform_file.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#include <windows.h> +#endif + +namespace base { + +class FilePath; + +class BASE_EXPORT MemoryMappedFile { + public: + // The default constructor sets all members to invalid/null values. + MemoryMappedFile(); + ~MemoryMappedFile(); + + // Opens an existing file and maps it into memory. Access is restricted to + // read only. If this object already points to a valid memory mapped file + // then this method will fail and return false. If it cannot open the file, + // the file does not exist, or the memory mapping fails, it will return false. + // Later we may want to allow the user to specify access. + bool Initialize(const FilePath& file_name); + // As above, but works with an already-opened file. MemoryMappedFile will take + // ownership of |file| and close it when done. + bool Initialize(PlatformFile file); + +#if defined(OS_WIN) + // Opens an existing file and maps it as an image section. Please refer to + // the Initialize function above for additional information. + bool InitializeAsImageSection(const FilePath& file_name); +#endif // OS_WIN + + const uint8* data() const { return data_; } + size_t length() const { return length_; } + + // Is file_ a valid file handle that points to an open, memory mapped file? + bool IsValid() const; + + private: + // Open the given file and pass it to MapFileToMemoryInternal(). + bool MapFileToMemory(const FilePath& file_name); + + // Map the file to memory, set data_ to that memory address. Return true on + // success, false on any kind of failure. This is a helper for Initialize(). + bool MapFileToMemoryInternal(); + + // Closes all open handles. Later we may want to make this public. + void CloseHandles(); + +#if defined(OS_WIN) + // MapFileToMemoryInternal calls this function. It provides the ability to + // pass in flags which control the mapped section. + bool MapFileToMemoryInternalEx(int flags); + + HANDLE file_mapping_; +#endif + PlatformFile file_; + uint8* data_; + size_t length_; + + DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile); +}; + +} // namespace base + +#endif // BASE_FILES_MEMORY_MAPPED_FILE_H_ diff --git a/base/files/memory_mapped_file_posix.cc b/base/files/memory_mapped_file_posix.cc new file mode 100644 index 0000000..38b2716 --- /dev/null +++ b/base/files/memory_mapped_file_posix.cc @@ -0,0 +1,54 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/memory_mapped_file.h" + +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "base/logging.h" +#include "base/posix/eintr_wrapper.h" +#include "base/threading/thread_restrictions.h" + +namespace base { + +MemoryMappedFile::MemoryMappedFile() + : file_(kInvalidPlatformFileValue), + data_(NULL), + length_(0) { +} + +bool MemoryMappedFile::MapFileToMemoryInternal() { + ThreadRestrictions::AssertIOAllowed(); + + struct stat file_stat; + if (fstat(file_, &file_stat) == kInvalidPlatformFileValue) { + DLOG(ERROR) << "Couldn't fstat " << file_ << ", errno " << errno; + return false; + } + length_ = file_stat.st_size; + + data_ = static_cast<uint8*>( + mmap(NULL, length_, PROT_READ, MAP_SHARED, file_, 0)); + if (data_ == MAP_FAILED) + DLOG(ERROR) << "Couldn't mmap " << file_ << ", errno " << errno; + + return data_ != MAP_FAILED; +} + +void MemoryMappedFile::CloseHandles() { + ThreadRestrictions::AssertIOAllowed(); + + if (data_ != NULL) + munmap(data_, length_); + if (file_ != kInvalidPlatformFileValue) + ignore_result(HANDLE_EINTR(close(file_))); + + data_ = NULL; + length_ = 0; + file_ = kInvalidPlatformFileValue; +} + +} // namespace base diff --git a/base/files/memory_mapped_file_win.cc b/base/files/memory_mapped_file_win.cc new file mode 100644 index 0000000..1a24de2 --- /dev/null +++ b/base/files/memory_mapped_file_win.cc @@ -0,0 +1,87 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/memory_mapped_file.h" + +#include "base/file_path.h" +#include "base/logging.h" +#include "base/metrics/histogram.h" +#include "base/string16.h" +#include "base/threading/thread_restrictions.h" + +namespace base { + +MemoryMappedFile::MemoryMappedFile() + : file_(INVALID_HANDLE_VALUE), + file_mapping_(INVALID_HANDLE_VALUE), + data_(NULL), + length_(INVALID_FILE_SIZE) { +} + +bool MemoryMappedFile::InitializeAsImageSection(const FilePath& file_name) { + if (IsValid()) + return false; + file_ = CreatePlatformFile(file_name, PLATFORM_FILE_OPEN | PLATFORM_FILE_READ, + NULL, NULL); + + if (file_ == kInvalidPlatformFileValue) { + DLOG(ERROR) << "Couldn't open " << file_name.AsUTF8Unsafe(); + return false; + } + + if (!MapFileToMemoryInternalEx(SEC_IMAGE)) { + CloseHandles(); + return false; + } + + return true; +} + +bool MemoryMappedFile::MapFileToMemoryInternal() { + return MapFileToMemoryInternalEx(0); +} + +bool MemoryMappedFile::MapFileToMemoryInternalEx(int flags) { + ThreadRestrictions::AssertIOAllowed(); + + if (file_ == INVALID_HANDLE_VALUE) + return false; + + length_ = ::GetFileSize(file_, NULL); + if (length_ == INVALID_FILE_SIZE) + return false; + + file_mapping_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY | flags, + 0, 0, NULL); + if (!file_mapping_) { + // According to msdn, system error codes are only reserved up to 15999. + // http://msdn.microsoft.com/en-us/library/ms681381(v=VS.85).aspx. + UMA_HISTOGRAM_ENUMERATION("MemoryMappedFile.CreateFileMapping", + logging::GetLastSystemErrorCode(), 16000); + return false; + } + + data_ = static_cast<uint8*>( + ::MapViewOfFile(file_mapping_, FILE_MAP_READ, 0, 0, 0)); + if (!data_) { + UMA_HISTOGRAM_ENUMERATION("MemoryMappedFile.MapViewOfFile", + logging::GetLastSystemErrorCode(), 16000); + } + return data_ != NULL; +} + +void MemoryMappedFile::CloseHandles() { + if (data_) + ::UnmapViewOfFile(data_); + if (file_mapping_ != INVALID_HANDLE_VALUE) + ::CloseHandle(file_mapping_); + if (file_ != INVALID_HANDLE_VALUE) + ::CloseHandle(file_); + + data_ = NULL; + file_mapping_ = file_ = INVALID_HANDLE_VALUE; + length_ = INVALID_FILE_SIZE; +} + +} // namespace base |