Make fopen() and stat() support UTF-8 paths on Windows
This commit is contained in:
@@ -90,3 +90,17 @@ bool cdio_charset_from_utf8(cdio_utf8_t * src, char ** dst,
|
||||
bool cdio_charset_to_utf8(char *src, size_t src_len, cdio_utf8_t **dst,
|
||||
const char * src_charset);
|
||||
|
||||
#ifdef _WIN32
|
||||
/** \brief Convert an UTF8 string to UTF-16 (allocate returned string)
|
||||
* \param str Source string
|
||||
* \returns NULL if the conversion was unsuccesful. Caller must free the
|
||||
* returned string.
|
||||
* This is a convenience function available on Windows platforms only.
|
||||
*/
|
||||
wchar_t* cdio_utf8_to_wchar(const char* str);
|
||||
|
||||
/** \brief Provides an UTF-8 compliant version of fopen for Windows
|
||||
* The parameters and return value are the same as fopen().
|
||||
*/
|
||||
FILE* fopen_utf8(const char* filename, const char* mode);
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
#include <cdio/logging.h>
|
||||
#include <cdio/util.h>
|
||||
@@ -55,11 +56,33 @@
|
||||
#define CDIO_FSEEK fseek
|
||||
#endif
|
||||
|
||||
/* Windows' fopen is not UTF-8 compliant, so we use our own */
|
||||
#if defined(_WIN32)
|
||||
#include <cdio/utf8.h>
|
||||
#define CDIO_FOPEN fopen_utf8
|
||||
#else
|
||||
#define CDIO_FOPEN fopen
|
||||
#endif
|
||||
|
||||
/* Use _stati64 if needed, on platforms that don't have transparent LFS support */
|
||||
#if defined(HAVE__STATI64) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
#define CDIO_STAT _stati64
|
||||
#define CDIO_STAT_STRUCT _stati64
|
||||
#if defined(_WIN32)
|
||||
/* Once again, use our own UTF-8 compliant version */
|
||||
static inline int _stati64_utf8(const char *path, struct _stati64 *buffer) {
|
||||
int ret;
|
||||
wchar_t* wpath = cdio_utf8_to_wchar(path);
|
||||
ret = _wstati64(wpath, buffer);
|
||||
free(wpath);
|
||||
return ret;
|
||||
}
|
||||
#define CDIO_STAT_CALL _stati64_utf8
|
||||
#else
|
||||
#define CDIO_STAT stat
|
||||
#define CDIO_STAT_CALL _stati64
|
||||
#endif
|
||||
#else
|
||||
#define CDIO_STAT_STRUCT stat
|
||||
#define CDIO_STAT_CALL stat
|
||||
#endif
|
||||
|
||||
#define _STRINGIFY(a) #a
|
||||
@@ -81,7 +104,7 @@ _stdio_open (void *user_data)
|
||||
{
|
||||
_UserData *const ud = user_data;
|
||||
|
||||
if ((ud->fd = fopen (ud->pathname, "rb")))
|
||||
if ((ud->fd = CDIO_FOPEN (ud->pathname, "rb")))
|
||||
{
|
||||
ud->fd_buf = calloc (1, CDIO_STDIO_BUFSIZE);
|
||||
setvbuf (ud->fd, ud->fd_buf, _IOFBF, CDIO_STDIO_BUFSIZE);
|
||||
@@ -224,7 +247,7 @@ cdio_stdio_new(const char pathname[])
|
||||
CdioDataSource_t *new_obj = NULL;
|
||||
cdio_stream_io_functions funcs = { NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
_UserData *ud = NULL;
|
||||
struct CDIO_STAT statbuf;
|
||||
struct CDIO_STAT_STRUCT statbuf;
|
||||
char* pathdup;
|
||||
|
||||
if (pathname == NULL)
|
||||
@@ -235,7 +258,7 @@ cdio_stdio_new(const char pathname[])
|
||||
if (pathdup == NULL)
|
||||
return NULL;
|
||||
|
||||
if (CDIO_STAT (pathdup, &statbuf) == -1)
|
||||
if (CDIO_STAT_CALL (pathdup, &statbuf) == -1)
|
||||
{
|
||||
cdio_warn ("could not retrieve file info for `%s': %s",
|
||||
pathdup, strerror (errno));
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <cdio/logging.h>
|
||||
#include <cdio/util.h>
|
||||
#include <cdio/utf8.h>
|
||||
#include <cdio/version.h>
|
||||
|
||||
#ifdef HAVE_STDIO_H
|
||||
@@ -65,6 +66,12 @@
|
||||
#define DEFAULT_CDIO_DEVICE "videocd.bin"
|
||||
#define DEFAULT_CDIO_CUE "videocd.cue"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CDIO_FOPEN fopen_utf8
|
||||
#else
|
||||
#define CDIO_FOPEN fopen
|
||||
#endif
|
||||
|
||||
static lsn_t get_disc_last_lsn_bincue (void *p_user_data);
|
||||
#include "image_common.h"
|
||||
static bool parse_cuefile (_img_private_t *cd, const char *toc_name);
|
||||
@@ -266,7 +273,7 @@ parse_cuefile (_img_private_t *cd, const char *psz_cue_name)
|
||||
if (NULL == psz_cue_name_dup)
|
||||
return false;
|
||||
|
||||
fp = fopen (psz_cue_name_dup, "r");
|
||||
fp = CDIO_FOPEN (psz_cue_name_dup, "r");
|
||||
free(psz_cue_name_dup);
|
||||
if (fp == NULL) {
|
||||
cdio_log(log_level, "error opening %s for reading: %s",
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <cdio/logging.h>
|
||||
#include <cdio/sector.h>
|
||||
#include <cdio/util.h>
|
||||
#include <cdio/utf8.h>
|
||||
#include <cdio/version.h>
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
@@ -69,6 +70,12 @@
|
||||
#define DEFAULT_CDIO_DEVICE "videocd.bin"
|
||||
#define DEFAULT_CDIO_CDRDAO "videocd.toc"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define CDIO_FOPEN fopen_utf8
|
||||
#else
|
||||
#define CDIO_FOPEN fopen
|
||||
#endif
|
||||
|
||||
#include "image_common.h"
|
||||
|
||||
static lsn_t get_disc_last_lsn_cdrdao (void *p_user_data);
|
||||
@@ -312,7 +319,7 @@ parse_tocfile (_img_private_t *cd, const char *psz_cue_name)
|
||||
if (NULL == psz_cue_name_dup)
|
||||
return false;
|
||||
|
||||
fp = fopen (psz_cue_name_dup, "r");
|
||||
fp = CDIO_FOPEN (psz_cue_name_dup, "r");
|
||||
free(psz_cue_name_dup);
|
||||
if (fp == NULL) {
|
||||
cdio_log(log_level, "error opening %s for reading: %s",
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_JOLIET
|
||||
#ifdef HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
@@ -43,6 +42,7 @@
|
||||
#include <cdio/utf8.h>
|
||||
#include <cdio/logging.h>
|
||||
|
||||
/* Windows requires some basic UTF-8 support outside of Joliet */
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
@@ -80,7 +80,7 @@ static inline char* cdio_wchar_to_utf8(const wchar_t* wstr)
|
||||
* Converts an UTF8 string to UTF-16 (allocate returned string)
|
||||
* Returns NULL on error
|
||||
*/
|
||||
static inline wchar_t* cdio_utf8_to_wchar(const char* str)
|
||||
wchar_t* cdio_utf8_to_wchar(const char* str)
|
||||
{
|
||||
int size = 0;
|
||||
wchar_t* wstr = NULL;
|
||||
@@ -99,8 +99,21 @@ static inline wchar_t* cdio_utf8_to_wchar(const char* str)
|
||||
}
|
||||
return wstr;
|
||||
}
|
||||
|
||||
/* UTF-8 compliant version of fopen() */
|
||||
FILE* fopen_utf8(const char* filename, const char* mode)
|
||||
{
|
||||
FILE* ret = NULL;
|
||||
wchar_t* wfilename = cdio_utf8_to_wchar(filename);
|
||||
wchar_t* wmode = cdio_utf8_to_wchar(mode);
|
||||
ret = _wfopen(wfilename, wmode);
|
||||
free(wfilename);
|
||||
free(wmode);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_JOLIET
|
||||
#ifdef HAVE_ICONV
|
||||
#include <iconv.h>
|
||||
struct cdio_charset_coverter_s
|
||||
|
||||
Reference in New Issue
Block a user