/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 "mem_map.h"

#include <windows.h>
// This include needs to be here due to the coding conventions.  Unfortunately
// it drags in the definition of the ERROR macro. Similarly to base/utils.cc,
// undefine the macro here. See also, the comment at android-base/logging.h.
#ifdef ERROR
#undef ERROR
#endif

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "android-base/mapped_file.h"
#ifdef PROT_READ
#undef PROT_READ
#endif
#ifdef PROT_WRITE
#undef PROT_WRITE
#endif
#include "mman.h"

namespace art {

using android::base::StringPrintf;

static off_t allocation_granularity;

void MemMap::TargetMMapInit() {
  SYSTEM_INFO si;
  GetSystemInfo(&si);
  allocation_granularity = si.dwAllocationGranularity;
}

void* MemMap::TargetMMap(void* start, size_t len, int prot, int flags, int fd, off_t fd_off) {
  UNUSED(start);
  size_t padding = fd_off % allocation_granularity;
  off_t file_offset = fd_off - padding;
  off_t map_length = len + padding;

  // Only read and write permissions are supported.
  if ((prot != PROT_READ) && (prot != (PROT_READ | PROT_WRITE))) {
    PLOG(ERROR) << "Protection or flag error was not supported.";
    errno = EINVAL;
    return MAP_FAILED;
  }
  // Fixed is not currently supported either.
  // TODO(sehr): add MAP_FIXED support.
  if ((flags & MAP_FIXED) != 0) {
    PLOG(ERROR) << "MAP_FIXED not supported.";
    errno = EINVAL;
    return MAP_FAILED;
  }

  // Compute the Windows access flags for the two APIs from the PROTs and MAPs.
  DWORD map_access = 0;
  DWORD view_access = 0;
  if ((prot & PROT_WRITE) != 0) {
    map_access = PAGE_READWRITE;
    if (((flags & MAP_SHARED) != 0) && ((flags & MAP_PRIVATE) == 0)) {
      view_access = FILE_MAP_ALL_ACCESS;
    } else if (((flags & MAP_SHARED) == 0) && ((flags & MAP_PRIVATE) != 0)) {
      view_access = FILE_MAP_COPY | FILE_MAP_READ;
    } else {
      PLOG(ERROR) << "MAP_PRIVATE and MAP_SHARED inconsistently set.";
      errno = EINVAL;
      return MAP_FAILED;
    }
  } else {
    map_access = PAGE_READONLY;
    view_access = FILE_MAP_READ;
  }

  // MapViewOfFile does not like to see a size greater than the file size of the
  // underlying file object, unless the underlying file object is writable.  If
  // the mapped region would go beyond the end of the underlying file, use zero,
  // as this indicates the physical size.
  HANDLE file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
  LARGE_INTEGER file_length;
  if (!::GetFileSizeEx(file_handle, &file_length)) {
    PLOG(ERROR) << "Couldn't get file size.";
    errno = EINVAL;
    return MAP_FAILED;
  }
  if (((map_access & PAGE_READONLY) != 0) &&
      file_offset + map_length > file_length.QuadPart) {
    map_length = 0;
  }

  // Create a file mapping object that will be used to access the file.
  HANDLE handle = ::CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)),
                                      nullptr,
                                      map_access,
                                      0,
                                      0,
                                      nullptr);
  if (handle == nullptr) {
    DWORD error = ::GetLastError();
    PLOG(ERROR) << StringPrintf("Couldn't create file mapping %lx.", error);
    errno = EINVAL;
    return MAP_FAILED;
  }

  // Map the file into the process address space.
  DWORD offset_low = static_cast<DWORD>(file_offset & 0xffffffffU);
#ifdef _WIN64
  DWORD offset_high = static_cast<DWORD>(file_offset >> 32);
#else
  DWORD offset_high = static_cast<DWORD>(0);
#endif
  void* view_address = MapViewOfFile(handle, view_access, offset_high, offset_low, map_length);
  if (view_address == nullptr) {
    DWORD error = ::GetLastError();
    PLOG(ERROR) << StringPrintf("Couldn't create file view %lx.", error);
    ::CloseHandle(handle);
    errno = EINVAL;
    return MAP_FAILED;
  }

  return view_address;
}

int MemMap::TargetMUnmap(void* start, size_t len) {
  // TODO(sehr): implement unmap.
  UNUSED(start);
  UNUSED(len);
  return 0;
}

}  // namespace art
