Skip to content

Commit fe53a41

Browse files
committed
fopen Windows wrapper to support reading UTF-8 encoded files
1 parent f7e30c7 commit fe53a41

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

contrib/win32/win32compat/inc/unistd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
#define getdtablesize() MAX_FDS
3737

38+
#define fopen w32_fopen_utf8
39+
3840
/* Compatibility header to avoid lots of #ifdefs in includes.h on Win32 */
3941

4042
#include <conio.h>

contrib/win32/win32compat/inc/w32posix.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ sighandler_t w32_signal(int signum, sighandler_t handler);
6969
int w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
7070
int w32_raise(int sig);
7171
int w32_kill(int pid, int sig);
72+
FILE* w32_fopen_utf8(const char *, const char *);
7273

7374

7475
/* Shutdown constants */

contrib/win32/win32compat/misc.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <Windows.h>
2+
#include <stdio.h>
23
#include "inc\defs.h"
34
#include "inc\sys\statvfs.h"
45

@@ -69,4 +70,51 @@ int dlclose(HMODULE handle) {
6970

7071
FARPROC dlsym(HMODULE handle, const char *symbol) {
7172
return GetProcAddress(handle, symbol);
73+
}
74+
75+
76+
/*fopen on Windows to mimic https://linux.die.net/man/3/fopen
77+
* only r, w, a are supported for now
78+
*/
79+
FILE*
80+
w32_fopen_utf8(const char *path, const char *mode) {
81+
wchar_t wpath[MAX_PATH], wmode[5];
82+
FILE* f;
83+
char utf8_bom[] = { 0xEF,0xBB,0xBF };
84+
char first3_bytes[3];
85+
86+
if (mode[1] != '\0') {
87+
errno = ENOTSUP;
88+
return NULL;
89+
}
90+
91+
if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, MAX_PATH) == 0 ||
92+
MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, 5) == 0) {
93+
errno = EFAULT;
94+
debug("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError());
95+
return NULL;
96+
}
97+
98+
f = _wfopen(wpath, wmode);
99+
100+
if (f) {
101+
/* BOM adjustments for file streams*/
102+
if (mode[0] == 'w' && fseek(f, 0, SEEK_SET) != EBADF) {
103+
/* write UTF-8 BOM - should we ?*/
104+
/*if (fwrite(utf8_bom, sizeof(utf8_bom), 1, f) != 1) {
105+
fclose(f);
106+
return NULL;
107+
}*/
108+
109+
}
110+
else if (mode[0] == 'r' && fseek(f, 0, SEEK_SET) != EBADF) {
111+
/* read out UTF-8 BOM if present*/
112+
if (fread(first3_bytes, 3, 1, f) != 1 ||
113+
memcmp(first3_bytes, utf8_bom, 3) != 0) {
114+
fseek(f, 0, SEEK_SET);
115+
}
116+
}
117+
}
118+
119+
return f;
72120
}

0 commit comments

Comments
 (0)