diff options
author | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-24 21:55:45 +0000 |
---|---|---|
committer | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-24 21:55:45 +0000 |
commit | c3088cbb5cbd5c91b6c5602750ec327ff7963862 (patch) | |
tree | 4aac06d2b2541d9ef2744f719478f6c2c88b00c1 /base/files | |
parent | 47e870bf26f0c01dafe611ec03c0139c735063df (diff) | |
download | chromium_src-c3088cbb5cbd5c91b6c5602750ec327ff7963862.zip chromium_src-c3088cbb5cbd5c91b6c5602750ec327ff7963862.tar.gz chromium_src-c3088cbb5cbd5c91b6c5602750ec327ff7963862.tar.bz2 |
base: Move MemoryMappedFile out of file_util.h and into its own header file.
BUG=175002
TEST=base_unittests
R=brettw@chromium.org
TBR=erikwright@chromium.org,tommi@chromium.org,fischman@chromium.org,ben@chromium.org
Review URL: https://chromiumcodereview.appspot.com/12321062
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184356 0039d316-1c4b-4281-b951-d872f2087c98
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 |