aboutsummaryrefslogtreecommitdiffstats
path: root/android/utils/mapfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'android/utils/mapfile.c')
-rw-r--r--android/utils/mapfile.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/android/utils/mapfile.c b/android/utils/mapfile.c
new file mode 100644
index 0000000..f964d38
--- /dev/null
+++ b/android/utils/mapfile.c
@@ -0,0 +1,250 @@
+/* Copyright (C) 2007-2010 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+*/
+
+/*
+ * Contains implementation of routines that implement platform-independent
+ * file I/O.
+ */
+
+#include "stddef.h"
+#include "sys/types.h"
+#include "errno.h"
+#ifdef WIN32
+#include "Windows.h"
+#else // WIN32
+#include <sys/mman.h>
+#endif // WIN32
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "mapfile.h"
+
+MapFile*
+mapfile_open(const char* path, int oflag, int share_mode)
+{
+#ifdef WIN32
+ DWORD win32_share;
+ DWORD win32_desired_access;
+ DWORD win32_disposition;
+ DWORD win32_flags;
+
+ /* Convert to Win32 desired access. */
+ if ((oflag & O_RDWR) == O_RDWR) {
+ win32_desired_access = GENERIC_READ | GENERIC_WRITE;
+ } else if ((oflag & O_ACCMODE) == O_RDONLY) {
+ win32_desired_access = GENERIC_READ;
+ } else if ((oflag & O_WRONLY) == O_WRONLY) {
+ win32_desired_access = GENERIC_WRITE;
+ }
+
+ /* Convert to Win32 sharing. */
+ win32_share = 0;
+ if ((share_mode & S_IWRITE) != 0) {
+ win32_share |= FILE_SHARE_WRITE;
+ }
+ if ((share_mode & S_IREAD) != 0) {
+ win32_share |= FILE_SHARE_READ;
+ }
+
+ /* Convert to Win32 disposition. */
+ if ((oflag & O_CREAT) == O_CREAT) {
+ if ((oflag & O_EXCL) == O_EXCL) {
+ win32_disposition = CREATE_NEW;
+ } else {
+ win32_disposition = OPEN_ALWAYS;
+ }
+ } if ((oflag & O_TRUNC) == O_TRUNC) {
+ win32_desired_access = TRUNCATE_EXISTING;
+ } else {
+ win32_disposition = OPEN_EXISTING;
+ }
+
+ /* Convert to Win32 flags. */
+ win32_flags = 0;
+#if defined(O_DSYNC)
+ if ((oflag & O_DSYNC) == O_DSYNC ||
+ (oflag & O_RSYNC) == O_RSYNC ||
+ (oflag & O_RSYNC) == O_SYNC) {
+ win32_flags |= FILE_FLAG_WRITE_THROUGH;
+ }
+#endif // O_DSYNC
+
+ HANDLE file_handle = CreateFile(path, win32_desired_access, win32_share,
+ NULL, win32_disposition, win32_flags, NULL);
+ if (file_handle == INVALID_HANDLE_VALUE) {
+ errno = GetLastError();
+ }
+#else // WIN32
+ int file_handle = open(path, oflag, share_mode);
+#endif // WIN32
+
+ return (MapFile*)file_handle;
+}
+
+int
+mapfile_close(MapFile* handle)
+{
+#ifdef WIN32
+ if (CloseHandle(handle)) {
+ return 0;
+ } else {
+ errno = GetLastError();
+ return -1;
+ }
+#else // WIN32
+ return close((int)handle);
+#endif // WIN32
+}
+
+ssize_t
+mapfile_read(MapFile* handle, void* buf, size_t nbyte)
+{
+#ifdef WIN32
+ ssize_t ret_bytes;
+ DWORD read_bytes;
+ if (ReadFile(handle, buf, nbyte, &read_bytes, NULL)) {
+ ret_bytes = (ssize_t)read_bytes;
+ } else {
+ errno = GetLastError();
+ ret_bytes = -1;
+ }
+ return ret_bytes;
+#else // WIN32
+ ssize_t ret;
+ do {
+ ret = read((int)handle, buf, nbyte);
+ } while (ret < 0 && errno == EINTR);
+ return ret;
+#endif // WIN32
+}
+
+ssize_t
+mapfile_read_at(MapFile* handle, size_t offset, void* buf, size_t nbyte)
+{
+#ifdef WIN32
+ LARGE_INTEGER convert;
+ convert.QuadPart = offset;
+ if ((SetFilePointer(handle, convert.LowPart, &convert.HighPart,
+ FILE_BEGIN) == INVALID_SET_FILE_POINTER) &&
+ (GetLastError() != NO_ERROR)) {
+ errno = GetLastError();
+ return -1;
+ }
+ return mapfile_read(handle, buf, nbyte);
+#else // WIN32
+ ssize_t res = lseek((int)handle, offset, SEEK_SET);
+ return res >= 0 ? mapfile_read(handle, buf, nbyte) : res;
+#endif // WIN32
+}
+
+void*
+mapfile_map(MapFile* handle,
+ size_t offset,
+ size_t size,
+ int prot,
+ void** mapped_offset,
+ size_t* mapped_size)
+{
+ void* mapped_at = NULL;
+ size_t align_mask;
+ size_t map_offset;
+ size_t map_size;
+
+ /* Get the mask for mapping offset alignment. */
+#ifdef WIN32
+ DWORD win32_prot;
+ DWORD win32_map;
+ HANDLE map_handle;
+ LARGE_INTEGER converter;
+ SYSTEM_INFO sys_info;
+ GetSystemInfo(&sys_info);
+ align_mask = sys_info.dwAllocationGranularity - 1;
+#else // WIN32
+ align_mask = getpagesize() - 1;
+#endif // WIN32
+
+ /* Adjust mapping offset and mapping size accordingly to
+ * the mapping alignment requirements. */
+ map_offset = offset & ~align_mask;
+ map_size = (size_t)(offset - map_offset + size);
+
+ /* Make sure mapping size doesn't exceed 4G. */
+ if (map_size < size) {
+ errno = EFBIG;
+ return NULL;
+ }
+
+ /* Map the section. */
+#ifdef WIN32
+ /* Convert to Win32 page protection and mapping type. */
+ win32_prot = PAGE_READONLY;
+ win32_map = FILE_MAP_READ;
+ if (prot != PROT_NONE) {
+ if ((prot & (PROT_WRITE | PROT_EXEC)) == 0) {
+ win32_prot = PAGE_READONLY;
+ win32_map = FILE_MAP_READ;
+ } else if ((prot & (PROT_WRITE | PROT_EXEC)) ==
+ (PROT_WRITE | PROT_EXEC)) {
+ win32_prot = PAGE_EXECUTE_READWRITE;
+ win32_map = FILE_MAP_WRITE;
+ } else if ((prot & PROT_WRITE) == PROT_WRITE) {
+ win32_prot = PAGE_READWRITE;
+ win32_map = FILE_MAP_WRITE;
+ } else if ((prot & PROT_EXEC) == PROT_EXEC) {
+ win32_prot = PAGE_EXECUTE_READ;
+ win32_map = FILE_MAP_READ;
+ }
+ }
+
+ converter.QuadPart = map_offset + map_size;
+ map_handle = CreateFileMapping(handle, NULL, win32_prot,
+ converter.HighPart, converter.LowPart, NULL);
+ if (map_handle != NULL) {
+ converter.QuadPart = map_offset;
+ mapped_at = MapViewOfFile(map_handle, win32_map, converter.HighPart,
+ converter.LowPart, map_size);
+ /* Memory mapping (if successful) will hold extra references to the
+ * mapping, so we can close it right after we mapped file view. */
+ CloseHandle(map_handle);
+ }
+ if (mapped_at == NULL) {
+ errno = GetLastError();
+ return NULL;
+ }
+#else // WIN32
+ mapped_at =
+ mmap(0, map_size, PROT_READ, MAP_SHARED, (int)handle, map_offset);
+ if (mapped_at == MAP_FAILED) {
+ return NULL;
+ }
+#endif // WIN32
+
+ *mapped_offset = (char*)mapped_at + (offset - map_offset);
+ *mapped_size = size;
+
+ return mapped_at;
+}
+
+int
+mapfile_unmap(void* mapped_at, size_t len)
+{
+#ifdef WIN32
+ if (!UnmapViewOfFile(mapped_at)) {
+ errno = GetLastError();
+ return -1;
+ }
+ return 0;
+#else // WIN32
+ return munmap(mapped_at, len);
+#endif // WIN32
+}