From f487953ad360b941fe225418cd3e5801d5a6508b Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Thu, 19 Dec 2013 15:00:50 +0200 Subject: Files: add wrappers for certain open() methods Due to filepath encoding issues on win32 we need wrappers for: - open() - fopen() - opendir() - zip_open() (this is readonly on win32) Patch only declares/defines the wrappers in dive.h, windows.c, linux.c, macos.c. Suggestions-by: Thiago Macieira Suggestions-by: Jef Driesen Signed-off-by: Lubomir I. Ivanov Signed-off-by: Dirk Hohndel --- dive.h | 7 +++++ linux.c | 28 +++++++++++++++++++ macos.c | 29 ++++++++++++++++++++ windows.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+) diff --git a/dive.h b/dive.h index 46c42fc4c..4f9b29509 100644 --- a/dive.h +++ b/dive.h @@ -5,6 +5,7 @@ #include #include #include +#include /* Windows has no MIN/MAX macros - so let's just roll our own */ #define MIN(x, y) ({ \ @@ -633,6 +634,12 @@ extern void save_dives_logic(const char *filename, bool select_only); extern void save_dive(FILE *f, struct dive *dive); extern void export_dives_uddf(const char *filename, const bool selected); +extern int subsurface_open(const char *path, int oflags, mode_t mode); +extern FILE *subsurface_fopen(const char *path, const char *mode); +extern void *subsurface_opendir(const char *path); +extern struct zip *subsurface_zip_open_readonly(const char *path, int flags, int *errorp); +extern int subsurface_zip_close(struct zip *zip); + extern void shift_times(const timestamp_t amount); extern xsltStylesheetPtr get_stylesheet(const char *name); diff --git a/linux.c b/linux.c index 5006ca011..1feefd6f1 100644 --- a/linux.c +++ b/linux.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include const char system_divelist_default_font[] = "Sans 8"; @@ -97,3 +99,29 @@ int enumerate_devices (device_callback_t callback, void *userdata) return index; } + +/* NOP wrappers to comform with windows.c */ +int subsurface_open(const char *path, int oflags, mode_t mode) +{ + return open(path, oflags, mode); +} + +FILE *subsurface_fopen(const char *path, const char *mode) +{ + return fopen(path, mode); +} + +void *subsurface_opendir(const char *path) +{ + return (void *)opendir(path); +} + +struct zip *subsurface_zip_open_readonly(const char *path, int flags, int *errorp) +{ + return zip_open(path, flags, errorp); +} + +int subsurface_zip_close(struct zip *zip) +{ + return zip_close(zip); +} diff --git a/macos.c b/macos.c index 64b23a792..ba461ee4f 100644 --- a/macos.c +++ b/macos.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include /* macos defines CFSTR to create a CFString object from a constant, * but no similar macros if a C string variable is supposed to be @@ -77,3 +80,29 @@ int enumerate_devices (device_callback_t callback, void *userdata) closedir (dp); return index; } + +/* NOP wrappers to comform with windows.c */ +int subsurface_open(const char *path, int oflags, mode_t mode) +{ + return open(path, oflags, mode); +} + +FILE *subsurface_fopen(const char *path, const char *mode) +{ + return fopen(path, mode); +} + +void *subsurface_opendir(const char *path) +{ + return (void *)opendir(path); +} + +struct zip *subsurface_zip_open_readonly(const char *path, int flags, int *errorp) +{ + return zip_open(path, flags, errorp); +} + +int subsurface_zip_close(struct zip *zip) +{ + return zip_close(zip); +} diff --git a/windows.c b/windows.c index ff6e2e036..536205c39 100644 --- a/windows.c +++ b/windows.c @@ -4,6 +4,11 @@ #include "display.h" #include #include +#include +#include +#include +#include +#include const char system_divelist_default_font[] = "Sans 8"; @@ -78,3 +83,91 @@ int enumerate_devices (device_callback_t callback, void *userdata) RegCloseKey(hKey); return index; } + +/* this function converts a utf-8 string to win32's utf-16 2 byte string. + * the caller function should manage the allocated memory. + */ +static wchar_t *utf8_to_utf16_fl(const char *utf8, char *file, int line) +{ + assert(utf8 != NULL); + assert(file != NULL); + assert(line); + /* estimate buffer size */ + const int sz = strlen(utf8) + 1; + wchar_t *utf16 = (wchar_t *)malloc(sizeof(wchar_t) * sz); + if (!utf16) { + fprintf(stderr, "%s:%d: %s %d.", file, line, "cannot allocate buffer of size", sz); + return NULL; + } + if (MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, sz)) + return utf16; + fprintf(stderr, "%s:%d: %s", file, line, "cannot convert string."); + free((void *)utf16); + return NULL; +} + +#define utf8_to_utf16(s) utf8_to_utf16_fl(s, __FILE__, __LINE__) + +/* bellow we provide a set of wrappers for some I/O functions to use wchar_t. + * on win32 this solves the issue that we need paths to be utf-16 encoded. + */ +int subsurface_open(const char *path, int oflags, mode_t mode) +{ + int ret = -1; + wchar_t *wpath = utf8_to_utf16(path); + if (wpath) { + ret = _wopen(wpath, oflags, mode); + free((void *)wpath); + return ret; + } + return ret; +} + +FILE *subsurface_fopen(const char *path, const char *mode) +{ + FILE *ret = NULL; + wchar_t *wpath = utf8_to_utf16(path); + if (wpath) { + const int len = strlen(mode); + wchar_t wmode[len + 1]; + for (int i = 0; i < len; i++) + wmode[i] = (wchar_t)mode[i]; + wmode[len] = 0; + ret = _wfopen(wpath, wmode); + free((void *)wpath); + return ret; + } + return ret; +} + +/* here we return a void pointer instead of _WDIR or DIR pointer */ +void *subsurface_opendir(const char *path) +{ + _WDIR *ret = NULL; + wchar_t *wpath = utf8_to_utf16(path); + if (wpath) { + ret = _wopendir(wpath); + free((void *)wpath); + return (void *)ret; + } + return (void *)ret; +} + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +/* we use zip_fdopen since zip_open doesn't have a wchar_t version */ +struct zip *subsurface_zip_open_readonly(const char *path, int flags, int *errorp) +{ + int fd = subsurface_open(path, O_RDONLY | O_BINARY, 0); + struct zip *ret = zip_fdopen(fd, flags, errorp); + if (!ret) + close(fd); + return ret; +} + +int subsurface_zip_close(struct zip *zip) +{ + return zip_close(zip); +} -- cgit v1.2.3-70-g09d2