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