1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/* -*- c -*-
* File: loadfile.h
* Author: Igor Vlasenko <vlasenko@imath.kiev.ua>
* Created: Thu Sep 8 17:16:48 2005
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef USE_MMAP
#ifdef WIN32
/*
* the win32 code of Viacheslav Sheveliov <slavash@aha.ru>
* viy: should work for win64 too.
*/
#include <windows.h>
#include <stdio.h>
static PSTRING mmap_load_file(const char *filepath) {
PSTRING memarea = { NULL, NULL };
HANDLE hFile, hMapObject = NULL;
hFile = CreateFile(
TEXT(filepath),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
if (hFile != INVALID_HANDLE_VALUE) {
hMapObject = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapObject) {
// Get a pointer to the file-mapped shared memory.
LPCTSTR lpvMem = (LPTSTR) MapViewOfFile(hMapObject, FILE_MAP_READ, 0, 0, 0);
if (lpvMem) {
// Everything OK!
memarea.begin = (char *) lpvMem;
memarea.endnext = memarea.begin + GetFileSize(hFile, NULL);
// After MapViewOfFile we don't need file handles no more.
// Undocumented, but it works! (In read-only mode?)
CloseHandle(hMapObject);
CloseHandle(hFile);
return memarea;
}
}
}
// Something goes wrong
{
// Save last error code, before any system call
DWORD dwLastError = GetLastError();
// Report error, if file size != 0
// Mapping of zero-length file cause CreateFileMapping to fail.
// So skip error messages in this case.
if (hFile == INVALID_HANDLE_VALUE && GetFileSize(hFile, NULL) != 0)
fprintf(stderr, "Could not open file '%s'. (system error#%ld)\n", filepath, dwLastError);
}
// Close all opened handles
if (hMapObject) CloseHandle(hMapObject);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
return memarea;
}
/* we use function, not define, because someday we may need its address */
static int mmap_unload_file(PSTRING memarea) { return UnmapViewOfFile((void*) memarea.begin) ? 0 : -1; };
/* define mmap_unload_file(map) (UnmapViewOfFile((LPCVOID) map.begin) ? 0 : -1) */
#else /* unix, sweet unix :) */
#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_SYS_STAT_H)
/* # define NULL 0 */
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h> /* open */
#include <unistd.h> /* close */
static
PSTRING
mmap_load_file (const char* filepath) {
int fd;
struct stat st;
size_t size_in_bytes;
PSTRING memarea={NULL,NULL};
fd = open(filepath, O_RDONLY);
if (fd == -1) return memarea; /* {NULL,NULL} */
fstat(fd, &st);
size_in_bytes = st.st_size;
/* mmap size_in_bytes+1 to avoid crash with empty file */
memarea.begin = (char *) mmap(0, size_in_bytes+1, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
memarea.endnext=memarea.begin+size_in_bytes;
return memarea;
}
static
int
mmap_unload_file (PSTRING memarea) {
/* destroying */
return munmap((void *)memarea.begin, memarea.endnext-memarea.begin);
}
#endif /* UNIX */
#endif /* WIN32 */
#else
/*
* system seems to have no mmap ;
* we use standard C buffered read
*/
#include <stdio.h>
static
PSTRING
mmap_load_file (const char* filepath) {
FILE *stream;
size_t size_in_bytes=0;
size_t realsize;
size_t chunksize=4096;
size_t memsize=chunksize;
PSTRING memarea={NULL,NULL};
char* writepoint;
/* text mode for HTML::Template compatibility */
stream = fopen(filepath, "r");
if (stream == NULL) return memarea; /* {NULL,NULL} */
/* mmap size_in_bytes+1 to avoid crash with empty file */
memarea.begin=(const char*) malloc(memsize+1);
writepoint=(char*)memarea.begin;
while (1) {
realsize=fread(writepoint, 1, chunksize, stream);
size_in_bytes+=realsize;
if (realsize==chunksize) {
writepoint+=chunksize;
if (size_in_bytes+chunksize>memsize) {
memsize*=2;
memarea.begin=(char*) realloc((char*)memarea.begin, memsize+1);
writepoint=((char*)memarea.begin)+size_in_bytes;
}
} else {
fclose(stream);
memarea.endnext=memarea.begin+size_in_bytes;
return memarea;
}
}
}
static
int
mmap_unload_file (PSTRING memarea) {
/* destroying */
free((char*)memarea.begin);
return 0;
}
#endif /* USE_MMAP */
|