diff options
author | Wez Furlong <wez@php.net> | 2003-02-28 01:47:28 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2003-02-28 01:47:28 +0000 |
commit | cd98ed7b0aa91f7427251aa3168e7c8523e7df75 (patch) | |
tree | 7a73e0b666965862a3f8c1706250bb9c4f3e4206 /main/streams/plain_wrapper.c | |
parent | 7be8179520a89609527a2d8c8defd53b222f10f8 (diff) | |
download | php-git-cd98ed7b0aa91f7427251aa3168e7c8523e7df75.tar.gz |
Implement memory mapping for win32.
Could do with some rigorous testing; simple readfile() tests here appear to work.
Diffstat (limited to 'main/streams/plain_wrapper.c')
-rw-r--r-- | main/streams/plain_wrapper.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index f121b8ce15..ce2a7a553d 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -149,6 +149,10 @@ typedef struct { char *last_mapped_addr; size_t last_mapped_len; #endif +#ifdef PHP_WIN32 + char *last_mapped_addr; + HANDLE file_mapping; +#endif } php_stdio_stream_data; PHPAPI php_stream *_php_stream_fopen_temporary_file(const char *dir, const char *pfx, char **opened_path STREAMS_DC TSRMLS_DC) @@ -362,6 +366,15 @@ static int php_stdiop_close(php_stream *stream, int close_handle TSRMLS_DC) munmap(data->last_mapped_addr, data->last_mapped_len); data->last_mapped_addr = NULL; } +#elif defined(PHP_WIN32) + if (data->last_mapped_addr) { + UnmapViewOfFile(data->last_mapped_addr); + data->last_mapped_addr = NULL; + } + if (data->file_mapping) { + CloseHandle(data->file_mapping); + data->file_mapping = NULL; + } #endif if (close_handle) { @@ -643,6 +656,88 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void return PHP_STREAM_OPTION_RETURN_ERR; } } +#elif defined(PHP_WIN32) + { + php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam; + HANDLE hfile = (HANDLE)_get_osfhandle(fd); + DWORD prot, acc, loffs = 0, delta = 0; + + switch (value) { + case PHP_STREAM_MMAP_SUPPORTED: + return hfile == INVALID_HANDLE_VALUE ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; + + case PHP_STREAM_MMAP_MAP_RANGE: + switch (range->mode) { + case PHP_STREAM_MAP_MODE_READONLY: + prot = PAGE_READONLY; + acc = FILE_MAP_READ; + break; + case PHP_STREAM_MAP_MODE_READWRITE: + prot = PAGE_READWRITE; + acc = FILE_MAP_READ | FILE_MAP_WRITE; + break; + case PHP_STREAM_MAP_MODE_SHARED_READONLY: + prot = PAGE_READONLY; + acc = FILE_MAP_READ; + /* TODO: we should assign a name for the mapping */ + break; + case PHP_STREAM_MAP_MODE_SHARED_READWRITE: + prot = PAGE_READWRITE; + acc = FILE_MAP_READ | FILE_MAP_WRITE; + /* TODO: we should assign a name for the mapping */ + break; + } + + /* create a mapping capable of viewing the whole file (this costs no real resources) */ + data->file_mapping = CreateFileMapping(hfile, NULL, prot, 0, 0, NULL); + + if (data->file_mapping == NULL) { + return PHP_STREAM_OPTION_RETURN_ERR; + } + + if (range->length == 0) { + range->length = GetFileSize(hfile, NULL) - range->offset; + } + + /* figure out how big a chunk to map to be able to view the part that we need */ + if (range->offset != 0) { + SYSTEM_INFO info; + DWORD gran; + + GetSystemInfo(&info); + gran = info.dwAllocationGranularity; + loffs = (range->offset / gran) * gran; + delta = range->offset - loffs; + } + + data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length); + + if (data->last_mapped_addr) { + /* give them back the address of the start offset they requested */ + range->mapped = data->last_mapped_addr + delta; + return PHP_STREAM_OPTION_RETURN_OK; + } + + CloseHandle(data->file_mapping); + data->file_mapping = NULL; + + return PHP_STREAM_OPTION_RETURN_ERR; + + case PHP_STREAM_MMAP_UNMAP: + if (data->last_mapped_addr) { + UnmapViewOfFile(data->last_mapped_addr); + data->last_mapped_addr = NULL; + CloseHandle(data->file_mapping); + data->file_mapping = NULL; + return PHP_STREAM_OPTION_RETURN_OK; + } + return PHP_STREAM_OPTION_RETURN_ERR; + + default: + return PHP_STREAM_OPTION_RETURN_ERR; + } + } + #endif return PHP_STREAM_OPTION_RETURN_NOTIMPL; |