summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Lubomir I. Ivanov <neolit123@gmail.com>2013-12-19 15:00:50 +0200
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-12-19 07:28:20 -0800
commitf487953ad360b941fe225418cd3e5801d5a6508b (patch)
treea284c375543c2de073d4df26500a35d7c30afbe6
parentcad0d45fe17abedcb86bcdae6896d42324efbf96 (diff)
downloadsubsurface-f487953ad360b941fe225418cd3e5801d5a6508b.tar.gz
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 <thiago@macieira.org> Suggestions-by: Jef Driesen <jefdriesen@telenet.be> Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--dive.h7
-rw-r--r--linux.c28
-rw-r--r--macos.c29
-rw-r--r--windows.c93
4 files changed, 157 insertions, 0 deletions
diff --git a/dive.h b/dive.h
index 46c42fc4c..4f9b29509 100644
--- a/dive.h
+++ b/dive.h
@@ -5,6 +5,7 @@
#include <stdint.h>
#include <time.h>
#include <math.h>
+#include <zip.h>
/* 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 <sys/types.h>
#include <dirent.h>
#include <fnmatch.h>
+#include <stdio.h>
+#include <fcntl.h>
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 <CoreServices/CoreServices.h>
#include <mach-o/dyld.h>
#include <sys/syslimits.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <dirent.h>
/* 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 <windows.h>
#include <shlobj.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <dirent.h>
+#include <zip.h>
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);
+}