Support read/write memory-mapped files.

See also: chromium-dev thread "Support for Writable Memory Mapped Files", specifically the last few messages starting with "And... we're back!".

BUG=546019

Review-Url: https://codereview.chromium.org/1798203002
Cr-Commit-Position: refs/heads/master@{#394868}
diff --git a/base/files/memory_mapped_file_posix.cc b/base/files/memory_mapped_file_posix.cc
index 1067fdc9..4899cf0cd 100644
--- a/base/files/memory_mapped_file_posix.cc
+++ b/base/files/memory_mapped_file_posix.cc
@@ -21,7 +21,8 @@
 
 #if !defined(OS_NACL)
 bool MemoryMappedFile::MapFileRegionToMemory(
-    const MemoryMappedFile::Region& region) {
+    const MemoryMappedFile::Region& region,
+    Access access) {
   ThreadRestrictions::AssertIOAllowed();
 
   off_t map_start = 0;
@@ -65,7 +66,23 @@
     length_ = static_cast<size_t>(region.size);
   }
 
-  data_ = static_cast<uint8_t*>(mmap(NULL, map_size, PROT_READ, MAP_SHARED,
+  int flags = 0;
+  switch (access) {
+    case READ_ONLY:
+      flags |= PROT_READ;
+      break;
+    case READ_WRITE:
+      flags |= PROT_READ | PROT_WRITE;
+      break;
+    case READ_WRITE_EXTEND:
+      // POSIX won't auto-extend the file when it is written so it must first
+      // be explicitly extended to the maximum size. Zeros will fill the new
+      // space.
+      file_.SetLength(std::max(file_.GetLength(), region.offset + region.size));
+      flags |= PROT_READ | PROT_WRITE;
+      break;
+  }
+  data_ = static_cast<uint8_t*>(mmap(NULL, map_size, flags, MAP_SHARED,
                                      file_.GetPlatformFile(), map_start));
   if (data_ == MAP_FAILED) {
     DPLOG(ERROR) << "mmap " << file_.GetPlatformFile();