Create cross platform fopen() wrapper

This commit is contained in:
shermp
2019-04-10 22:25:29 +12:00
parent 3271c06c05
commit 7bb894eb0d
3 changed files with 35 additions and 14 deletions

View File

@@ -197,21 +197,10 @@ static VHDError vhd_load_parent(VHDMeta* vhdm, FILE* f, const char* child_filepa
/* (Hopefully) get the absolute path of the parent VHD */
cwk_path_get_absolute(child_dir, u8_rel_path, abs_path, sizeof abs_path);
free(u8_rel_path);
#ifdef _WIN32
uint16_t w_filemode[3] = {0x0072, 0x0062, 0x0000}; /* "rb" */
char *w_abs_path = NULL;
vhd_utf_convert(VHD_UTF_16_LE, abs_path, &w_abs_path);
FILE* par_f = _wfopen((uint16_t*)w_abs_path, w_filemode);
FILE* par_f = vhd_fopen(abs_path, "rb");
if (par_f) {
vhdm->parent.f = par_f;
}
free(w_abs_path);
#else
FILE* par_f = fopen(abs_path, "rb");
if (par_f) {
vhdm->parent.f = par_f;
}
#endif
vhdm->parent.meta = calloc(1, sizeof(VHDMeta));
return VHD_RET_OK;
}

View File

@@ -1,12 +1,14 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "vhdutil.h"
#include <error.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <iconv.h>
#include <error.h>
#endif
#include "vhdutil.h"
int vhd_utf_convert(VHDUtfType toUTF, void* in_str, char** out_str)
{
@@ -56,4 +58,32 @@ size_t vhd_u16_strlen(uint16_t* u16_str) {
u16_str += 1;
}
return count;
}
FILE* vhd_fopen(char* utf8_path, char* mode)
{
#ifdef _WIN32
errno_t err = 0;
char* u16_path = NULL;
WCHAR u16_mode[5] = {0};
/* Convert mode to UTF-16LE. Thankfully it's ASCII, which make the conversion simple...
Note, we're on Windows, so guaranteed to be little endian, therefore, no byte swapping needed. */
int mode_len = strlen(mode);
if (mode_len > 0 && mode_len < 5) {
for (int i = 0; i < mode_len; i++) {
u16_mode[i] = (WCHAR)mode[i];
}
}
/* Convert utf8_path to UTF-16LE */
vhd_utf_convert(VHD_UTF_16_LE, utf8_path, &u16_path);
FILE* f = _wfopen((LPCWCH)u16_path, u16_mode);
if (f == NULL) {_get_errno(&err);}
free(u16_path);
/* We want to mimic (_w)fopen() behavior */
if (err) {_set_errno(err);}
return f;
#else
/* Non-Windows OS's speak UTF-8 for fopen() */
return fopen(utf8_path, mode);
#endif
}

View File

@@ -15,4 +15,6 @@ int vhd_utf_convert(VHDUtfType toUTF, void* in_str, char** out_str);
/* Count the number of "characters" in a null terminated UTF-16 string. Not a true character count, as surrogate
pairs are counted as two "characters". Appears to be the Windows definition of a character for filepath
purposes. */
size_t vhd_u16_strlen(uint16_t* u16_str);
size_t vhd_u16_strlen(uint16_t* u16_str);
/* Cross platform function to open a (potentially) non-ascii filepath */
FILE* vhd_fopen(char* utf8_path, char* mode);