171 lines
3.4 KiB
C
Raw Normal View History

#include <stdlib.h>
#include <windows.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <errno.h>
#include "mman.h"
static const char id[]="$Id: tpl.c 107 2007-04-20 17:11:29Z thanson $";
/**
* @brief Map a file to a memory region
*
* This function emulates the POSIX mmap() using CreateFileMapping() and
* MapViewOfFile()
*
* @param addr the suggested start address (if != 0)
* @param len length of the region
* @param prot region accesibility, bitwise OR of PROT_READ, PROT_WRITE, PROT_EXEC
* @param flags mapping type and options (ignored)
* @param fd object to be mapped into memory
* @param offset offset into mapped object
* @return pointer to the memory region, or NULL in case of error
*/
void *mmap(void *addr, unsigned int len, int prot, int flags, int fd, unsigned int offset)
{
DWORD wprot;
DWORD waccess;
HANDLE h;
void *region;
/* Translate read/write/exec flags into WIN32 constants */
switch (prot) {
case PROT_READ:
wprot = PAGE_READONLY;
break;
case PROT_EXEC:
wprot = PAGE_EXECUTE_READ;
break;
case PROT_READ | PROT_EXEC:
wprot = PAGE_EXECUTE_READ;
break;
case PROT_WRITE:
wprot = PAGE_READWRITE;
break;
case PROT_READ | PROT_WRITE:
wprot = PAGE_READWRITE;
break;
case PROT_READ | PROT_WRITE | PROT_EXEC:
wprot = PAGE_EXECUTE_READWRITE;
break;
case PROT_WRITE | PROT_EXEC:
wprot = PAGE_EXECUTE_READWRITE;
break;
}
/* Obtaing handle to map region */
h = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, wprot, 0, len, 0);
if (h == NULL) {
DWORD error = GetLastError();
/* Try and translate some error codes */
switch (error) {
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_ACCESS:
errno = EACCES;
break;
case ERROR_OUTOFMEMORY:
case ERROR_NOT_ENOUGH_MEMORY:
errno = ENOMEM;
break;
default:
errno = EINVAL;
break;
}
return MAP_FAILED;
}
/* Translate sharing options into WIN32 constants */
switch (wprot) {
case PAGE_READONLY:
waccess = FILE_MAP_READ;
break;
case PAGE_READWRITE:
waccess = FILE_MAP_WRITE;
break;
}
/* Map file and return pointer */
region = MapViewOfFile(h, waccess, 0, 0, 0);
if (region == NULL) {
DWORD error = GetLastError();
/* Try and translate some error codes */
switch (error) {
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_ACCESS:
errno = EACCES;
break;
case ERROR_INVALID_HANDLE:
errno = EBADF;
break;
default:
errno = EINVAL;
break;
}
CloseHandle(h);
return MAP_FAILED;
}
/* All fine */
return region;
}
/**
* @brief Unmap a memory region
*
* This is a wrapper around UnmapViewOfFile in the win32 API
*
* @param addr start address
* @param len length of the region
* @return 0 for success, -1 for error
*/
int munmap(void *addr, int len)
{
if (UnmapViewOfFile(addr)) {
return 0;
}
else {
errno = EINVAL;
return -1;
}
}
/**
* Synchronize a mapped region
*
* This is a wrapper around FlushViewOfFile
*
* @param addr start address
* @param len number of bytes to flush
* @param flags sync options -- currently ignored
* @return 0 for success, -1 for error
*/
int msync(char *addr, int len, int flags)
{
if (FlushViewOfFile(addr, len) == 0) {
DWORD error = GetLastError();
/* Try and translate some error codes */
switch (error) {
case ERROR_INVALID_PARAMETER:
errno = EINVAL;
break;
case ERROR_WRITE_FAULT:
errno = EIO;
break;
default:
errno = EINVAL;
break;
}
return -1;
}
/* Success */
return 0;
}