D605: Fixes for proper handling of wchar_t paths in MinGW.
* Fixed different not-in-sync #ifdef blocks for struct stat variants under Windows. Comments have been left to indicate the portions of BLI_fileops.h and BLI_fileops_types.h that need to stay in sync. * Added BLI_wstat() to de-duplicate #ifdef blocks for stat() variants on Windows. * Fix for opendir() and associate functions in MinGW not working properly with non-ASCII, MBCS-compatible paths. MinGW (FREE_WINDOWS) has opendir() and _wopendir(), and only the latter accepts a path name of wchar_t type. Rather than messing up with extra #ifdef's here and there, Blender's own implementations of opendir() and related functions are used to properly support paths with non-ASCII, MBCS-compatible characters. Tested with MSVC 2013 Express, MinGW32 (gcc 4.6.2) and MinGW-w64 (gcc 4.7.1). Differential Revision: https://developer.blender.org/D605 Reviewed By: campbellbarton
This commit is contained in:
@@ -60,17 +60,23 @@ int BLI_delete(const char *path, bool dir, bool recursive);
|
|||||||
int BLI_move(const char *path, const char *to);
|
int BLI_move(const char *path, const char *to);
|
||||||
int BLI_create_symlink(const char *path, const char *to);
|
int BLI_create_symlink(const char *path, const char *to);
|
||||||
|
|
||||||
|
/* keep in sync with the definition of struct direntry in BLI_fileops_types.h */
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
# ifndef __MINGW64__
|
# if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
|
||||||
typedef struct _stat64 BLI_stat_t;
|
typedef struct _stat64 BLI_stat_t;
|
||||||
|
# elif defined(__MINGW32__)
|
||||||
|
typedef struct _stati64 BLI_stat_t;
|
||||||
# else
|
# else
|
||||||
typedef struct stat BLI_stat_t;
|
typedef struct _stat BLI_stat_t;
|
||||||
#endif
|
# endif
|
||||||
#else
|
#else
|
||||||
typedef struct stat BLI_stat_t;
|
typedef struct stat BLI_stat_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int BLI_stat(const char *path, BLI_stat_t *buffer);
|
int BLI_stat(const char *path, BLI_stat_t *buffer);
|
||||||
|
#ifdef WIN32
|
||||||
|
int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Directories */
|
/* Directories */
|
||||||
|
|
||||||
|
@@ -45,10 +45,14 @@ struct direntry {
|
|||||||
mode_t type;
|
mode_t type;
|
||||||
char *relname;
|
char *relname;
|
||||||
char *path;
|
char *path;
|
||||||
#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__) && (_MSC_VER >= 1500)
|
#ifdef WIN32 /* keep in sync with the definition of BLI_stat_t in BLI_fileops.h */
|
||||||
|
# if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
|
||||||
struct _stat64 s;
|
struct _stat64 s;
|
||||||
#elif defined(__MINGW32__)
|
# elif defined(__MINGW32__)
|
||||||
struct _stati64 s;
|
struct _stati64 s;
|
||||||
|
# else
|
||||||
|
struct _stat s;
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
struct stat s;
|
struct stat s;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -125,10 +125,6 @@ typedef long ssize_t;
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef FREE_WINDOWS
|
|
||||||
#include <dirent.h>
|
|
||||||
#else
|
|
||||||
struct dirent {
|
struct dirent {
|
||||||
int d_ino;
|
int d_ino;
|
||||||
int d_off;
|
int d_off;
|
||||||
@@ -151,7 +147,6 @@ typedef struct _DIR {
|
|||||||
DIR *opendir(const char *path);
|
DIR *opendir(const char *path);
|
||||||
struct dirent *readdir(DIR *dp);
|
struct dirent *readdir(DIR *dp);
|
||||||
int closedir(DIR *dp);
|
int closedir(DIR *dp);
|
||||||
#endif
|
|
||||||
|
|
||||||
void RegisterBlendExtension(void);
|
void RegisterBlendExtension(void);
|
||||||
void get_default_root(char *root);
|
void get_default_root(char *root);
|
||||||
|
@@ -255,22 +255,7 @@ static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname)
|
|||||||
file->relname = dlink->name;
|
file->relname = dlink->name;
|
||||||
file->path = BLI_strdupcat(dirname, dlink->name);
|
file->path = BLI_strdupcat(dirname, dlink->name);
|
||||||
BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name);
|
BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name);
|
||||||
// use 64 bit file size, only needed for WIN32 and WIN64.
|
BLI_stat(fullname, &file->s);
|
||||||
// Excluding other than current MSVC compiler until able to test
|
|
||||||
#ifdef WIN32
|
|
||||||
{
|
|
||||||
wchar_t *name_16 = alloc_utf16_from_8(fullname, 0);
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
|
||||||
_wstat64(name_16, &file->s);
|
|
||||||
#elif defined(__MINGW32__)
|
|
||||||
_stati64(fullname, &file->s);
|
|
||||||
#endif
|
|
||||||
free(name_16);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
stat(fullname, &file->s);
|
|
||||||
#endif
|
|
||||||
file->type = file->s.st_mode;
|
file->type = file->s.st_mode;
|
||||||
file->flags = 0;
|
file->flags = 0;
|
||||||
dir_ctx->nrfiles++;
|
dir_ctx->nrfiles++;
|
||||||
@@ -473,11 +458,7 @@ size_t BLI_file_size(const char *path)
|
|||||||
int BLI_exists(const char *name)
|
int BLI_exists(const char *name)
|
||||||
{
|
{
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#ifndef __MINGW32__
|
BLI_stat_t st;
|
||||||
struct _stat64 st;
|
|
||||||
#else
|
|
||||||
struct _stati64 st;
|
|
||||||
#endif
|
|
||||||
wchar_t *tmp_16 = alloc_utf16_from_8(name, 1);
|
wchar_t *tmp_16 = alloc_utf16_from_8(name, 1);
|
||||||
int len, res;
|
int len, res;
|
||||||
unsigned int old_error_mode;
|
unsigned int old_error_mode;
|
||||||
@@ -506,11 +487,7 @@ int BLI_exists(const char *name)
|
|||||||
* when looking for a file on an empty CD/DVD drive */
|
* when looking for a file on an empty CD/DVD drive */
|
||||||
old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
||||||
|
|
||||||
#ifndef __MINGW32__
|
res = BLI_wstat(tmp_16, &st);
|
||||||
res = _wstat64(tmp_16, &st);
|
|
||||||
#else
|
|
||||||
res = _wstati64(tmp_16, &st);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SetErrorMode(old_error_mode);
|
SetErrorMode(old_error_mode);
|
||||||
|
|
||||||
@@ -530,16 +507,22 @@ int BLI_stat(const char *path, BLI_stat_t *buffer)
|
|||||||
int r;
|
int r;
|
||||||
UTF16_ENCODE(path);
|
UTF16_ENCODE(path);
|
||||||
|
|
||||||
/* workaround error in MinGW64 headers, normally, a wstat should work */
|
r = BLI_wstat(path_16, buffer);
|
||||||
#ifndef __MINGW64__
|
|
||||||
r = _wstat64(path_16, buffer);
|
|
||||||
#else
|
|
||||||
r = _wstati64(path_16, buffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
UTF16_UN_ENCODE(path);
|
UTF16_UN_ENCODE(path);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer)
|
||||||
|
{
|
||||||
|
#if (defined(_MSC_VER) && (_MSC_VER >= 1500)) || defined(__MINGW64__)
|
||||||
|
return _wstat64(path, buffer);
|
||||||
|
#elif defined(__MINGW32__)
|
||||||
|
return _wstati64(path, buffer);
|
||||||
|
#else
|
||||||
|
return _wstat(path, buffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
int BLI_stat(const char *path, struct stat *buffer)
|
int BLI_stat(const char *path, struct stat *buffer)
|
||||||
{
|
{
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
* (opendir, readdir, closedir)
|
* (opendir, readdir, closedir)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(FREE_WINDOWS)
|
#ifdef WIN32
|
||||||
|
|
||||||
/* standalone for inclusion in binaries other then blender */
|
/* standalone for inclusion in binaries other then blender */
|
||||||
# ifdef USE_STANDALONE
|
# ifdef USE_STANDALONE
|
||||||
@@ -44,6 +44,13 @@
|
|||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
#include "utfconv.h"
|
#include "utfconv.h"
|
||||||
|
|
||||||
|
/* Note: MinGW (FREE_WINDOWS) has opendir() and _wopendir(), and only the
|
||||||
|
* latter accepts a path name of wchar_t type. Rather than messing up with
|
||||||
|
* extra #ifdef's here and there, Blender's own implementations of opendir()
|
||||||
|
* and related functions are used to properly support paths with non-ASCII
|
||||||
|
* characters. (kjym3)
|
||||||
|
*/
|
||||||
|
|
||||||
DIR *opendir(const char *path)
|
DIR *opendir(const char *path)
|
||||||
{
|
{
|
||||||
wchar_t *path_16 = alloc_utf16_from_8(path, 0);
|
wchar_t *path_16 = alloc_utf16_from_8(path, 0);
|
||||||
|
Reference in New Issue
Block a user