From ae76545a0094114ef29dba52df97e69ab28b3dbc Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Sun, 3 Mar 2013 09:50:44 +0100 Subject: Abstract mmap() into a compat API The Win32 for mmap() is very different from Unix, so abstract this into our own p11_mmap_xxx() functions. --- common/compat.c | 158 +++++++++++++++++++++++++++++++++++++---------- common/compat.h | 16 +++++ common/tests/frob-cert.c | 35 ++++------- tools/tests/test.c | 2 + trust/parser.c | 28 +++------ 5 files changed, 160 insertions(+), 79 deletions(-) diff --git a/common/compat.c b/common/compat.c index 33e608f..af28e1d 100644 --- a/common/compat.c +++ b/common/compat.c @@ -175,6 +175,10 @@ basename (const char *name) #endif /* HAVE_BASENAME */ #ifdef OS_UNIX +#include +#include +#include +#include void p11_mutex_init (p11_mutex_t *mutex) @@ -196,6 +200,57 @@ p11_dl_error (void) return msg ? strdup (msg) : NULL; } +struct _p11_mmap { + int fd; + void *data; + size_t size; +}; + +p11_mmap * +p11_mmap_open (const char *path, + void **data, + size_t *size) +{ + struct stat sb; + p11_mmap *map; + + map = calloc (1, sizeof (p11_mmap)); + if (map == NULL) + return NULL; + + map->fd = open (path, O_RDONLY); + if (map->fd == -1) { + free (map); + return NULL; + } + + if (fstat (map->fd, &sb) < 0) { + close (map->fd); + free (map); + return NULL; + } + + map->size = sb.st_size; + map->data = mmap (NULL, map->size, PROT_READ, MAP_PRIVATE, map->fd, 0); + if (data == NULL) { + close (map->fd); + free (map); + return NULL; + } + + *data = map->data; + *size = map->size; + return map; +} + +void +p11_mmap_close (p11_mmap *map) +{ + munmap (map->data, map->size); + close (map->fd); + free (map); +} + #endif /* OS_UNIX */ #ifdef OS_WIN32 @@ -246,43 +301,78 @@ p11_thread_join (p11_thread_t thread) return 0; } -#endif /* OS_WIN32 */ +struct _p11_mmap { + HANDLE file; + HANDLE mapping; + void *data; +}; -#ifndef HAVE_STRNSTR +p11_mmap * +p11_mmap_open (const char *path, + void **data, + size_t *size) +{ + HANDLE mapping; + LARGE_INTEGER large; + DWORD errn; + p11_mmap *map; -/*- - * Copyright (c) 2001 Mike Barcroft - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ + map = calloc (1, sizeof (p11_mmap)); + if (map == NULL) + return NULL; + + map->file = CreateFile (path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); + if (map->file == INVALID_HANDLE_VALUE) { + errn = GetLastError (); + free (map); + SetLastError (errn); + return NULL; + } + if (!GetFileSizeEx (map->file, &large)) { + errn = GetLastError (); + CloseHandle (map->file); + free (map); + SetLastError (errn); + return NULL; + } + + mapping = CreateFileMapping (map->file, NULL, PAGE_READONLY, 0, 0, NULL); + if (!mapping) { + errn = GetLastError (); + CloseHandle (map->file); + free (map); + SetLastError (errn); + return NULL; + } + + map->data = MapViewOfFile (mapping, FILE_MAP_READ, 0, 0, large.QuadPart); + CloseHandle (mapping); + + if (map->data == NULL) { + errn = GetLastError (); + CloseHandle (map->file); + free (map); + SetLastError (errn); + return NULL; + } + + *data = map->data; + *size = large.QuadPart; + return map; +} + +void +p11_mmap_close (p11_mmap *map) +{ + UnmapViewOfFile (map->data); + CloseHandle (map->file); + free (map); +} + +#endif /* OS_WIN32 */ + +#ifndef HAVE_STRNSTR #include /* diff --git a/common/compat.h b/common/compat.h index 1b74a35..ad80ca5 100644 --- a/common/compat.h +++ b/common/compat.h @@ -133,6 +133,14 @@ char * p11_dl_error (void); #define p11_sleep_ms(ms) \ (Sleep (ms)) +typedef struct _p11_mmap p11_mmap; + +p11_mmap * p11_mmap_open (const char *path, + void **data, + size_t *size); + +void p11_mmap_close (p11_mmap *map); + #endif /* OS_WIN32 */ /* ---------------------------------------------------------------------------- @@ -186,6 +194,14 @@ char * p11_dl_error (void); nanosleep (&_ts, NULL); \ } while(0) +typedef struct _p11_mmap p11_mmap; + +p11_mmap * p11_mmap_open (const char *path, + void **data, + size_t *size); + +void p11_mmap_close (p11_mmap *map); + #endif /* OS_UNIX */ #ifdef HAVE_ERRNO_H diff --git a/common/tests/frob-cert.c b/common/tests/frob-cert.c index f8ad392..71018bd 100644 --- a/common/tests/frob-cert.c +++ b/common/tests/frob-cert.c @@ -37,7 +37,6 @@ #include -#include #include #include @@ -86,12 +85,12 @@ main (int argc, char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, }; node_asn *definitions = NULL; node_asn *cert = NULL; - unsigned char *data; - struct stat sb; + p11_mmap *map; + void *data; + size_t size; int start, end; ssize_t len; int ret; - int fd; if (argc != 4) { fprintf (stderr, "usage: frob-cert struct field filename\n"); @@ -107,38 +106,26 @@ main (int argc, ret = asn1_create_element (definitions, argv[1], &cert); err_if_fail (ret, "Certificate"); - fd = open (argv[3], O_RDONLY); - if (fd == -1) { + map = p11_mmap_open (argv[3], &data, &size); + if (map == NULL) { fprintf (stderr, "couldn't open file: %s\n", argv[3]); return 1; } - if (fstat (fd, &sb) < 0) { - fprintf (stderr, "couldn't stat file: %s\n", argv[3]); - return 1; - } - - data = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (data == NULL) { - fprintf (stderr, "couldn't map file: %s\n", argv[3]); - return 1; - } - - ret = asn1_der_decoding (&cert, data, sb.st_size, message); + ret = asn1_der_decoding (&cert, data, size, message); err_if_fail (ret, message); - ret = asn1_der_decoding_startEnd (cert, data, sb.st_size, argv[2], &start, &end); + ret = asn1_der_decoding_startEnd (cert, data, size, argv[2], &start, &end); err_if_fail (ret, "asn1_der_decoding_startEnd"); - len = tlv_length (data + start, sb.st_size - start); + len = tlv_length ((unsigned char *)data + start, size - start); assert (len >= 0); - fprintf (stderr, "%lu %d %d %ld\n", sb.st_size, start, end, len); - fwrite (data + start, 1, len, stdout); + fprintf (stderr, "%lu %d %d %ld\n", (unsigned long)size, start, end, (long)len); + fwrite ((unsigned char *)data + start, 1, len, stdout); fflush (stdout); - munmap (data, sb.st_size); - close (fd); + p11_mmap_close (map); asn1_delete_structure (&cert); asn1_delete_structure (&definitions); diff --git a/tools/tests/test.c b/tools/tests/test.c index ecc0410..c445099 100644 --- a/tools/tests/test.c +++ b/tools/tests/test.c @@ -38,6 +38,8 @@ #include "debug.h" #include "test.h" +#include + #include #include #include diff --git a/trust/parser.c b/trust/parser.c index 6229d09..3448f40 100644 --- a/trust/parser.c +++ b/trust/parser.c @@ -52,7 +52,6 @@ #include -#include #include #include @@ -1043,33 +1042,20 @@ p11_parse_file (p11_parser *parser, p11_parser_sink sink, void *sink_data) { + p11_mmap *map; void *data; - struct stat sb; - int fd; + size_t size; int ret; - fd = open (filename, O_RDONLY); - if (fd == -1) { - p11_message ("couldn't open file: %s: %s", filename, strerror (errno)); + map = p11_mmap_open (filename, &data, &size); + if (map == NULL) { + p11_message ("couldn't open and map file: %s: %s", filename, strerror (errno)); return P11_PARSE_FAILURE; } - if (fstat (fd, &sb) < 0) { - p11_message ("couldn't stat file: %s: %s", filename, strerror (errno)); - return P11_PARSE_FAILURE; - } - - data = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (data == NULL) { - p11_message ("couldn't map file: %s: %s", filename, strerror (errno)); - return P11_PARSE_FAILURE; - } - - ret = p11_parse_memory (parser, filename, flags, data, sb.st_size, sink, sink_data); - - munmap (data, sb.st_size); - close (fd); + ret = p11_parse_memory (parser, filename, flags, data, size, sink, sink_data); + p11_mmap_close (map); return ret; } -- cgit v1.1