Windows wide path conversions: don't use SYSPATH outside pathut.cpp

This commit is contained in:
Jean-Francois Dockes 2020-09-30 12:31:51 +01:00
parent a15b2d5f45
commit e8a5ee327d
4 changed files with 51 additions and 13 deletions

View File

@ -78,6 +78,7 @@
#include <dirent.h>
#endif // _MSC_VER
#ifdef _WIN32
#ifndef _MSC_VER
@ -134,6 +135,10 @@
#define RMDIR _wrmdir
#define CHDIR _wchdir
#define SYSPATH(PATH, SPATH) wchar_t PATH ## _buf[2048]; \
utf8towchar(PATH, PATH ## _buf, 2048); \
wchar_t *SPATH = PATH ## _buf;
#define ftruncate _chsize_s
#ifdef _MSC_VER
@ -172,6 +177,9 @@
#define RMDIR ::rmdir
#define CHDIR ::chdir
#define SYSPATH(PATH, SPATH) const char *SPATH = PATH.c_str()
#endif /* !_WIN32 */
using namespace std;
@ -256,6 +264,31 @@ bool utf8towchar(const std::string& in, wchar_t *out, size_t obytescap)
return true;
}
std::unique_ptr<wchar_t[]> utf8towchar(const std::string& in)
{
// Note that as we supply in.size(), mbtowch computes the size
// without a terminating 0 (and won't write in the second call of
// course). We take this into account by allocating one more and
// terminating the output.
int wcharcnt = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, in.c_str(), in.size(), nullptr, 0);
if (wcharcnt <= 0) {
LOGERR("utf8towchar: conversion error for [" << in << "]\n");
return std::unique_ptr<wchar_t[]>();
}
auto buf = unique_ptr<wchar_t[]>(new wchar_t[wcharcnt+1]);
wcharcnt = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, in.c_str(), in.size(),
buf.get(), wcharcnt);
if (wcharcnt <= 0) {
LOGERR("utf8towchar: conversion error for [" << in << "]\n");
return std::unique_ptr<wchar_t[]>();
}
buf.get()[wcharcnt] = 0;
return buf;
}
/// Convert \ separators to /
void path_slashize(string& s)
{

View File

@ -123,14 +123,10 @@ extern int path_fileprops(const std::string path, struct PathStat *stp,
extern std::string path_PATHsep();
#ifdef _WIN32
extern bool wchartoutf8(const wchar_t *in, std::string& out, size_t len = 0);
extern std::string wchartoutf8(const wchar_t *in, size_t len = 0);
extern bool utf8towchar(const std::string& in, wchar_t *out, size_t obytescap);
#define SYSPATH(PATH, SPATH) wchar_t PATH ## _buf[2048]; \
utf8towchar(PATH, PATH ## _buf, 2048); \
wchar_t *SPATH = PATH ## _buf;
#else
#define SYSPATH(PATH, SPATH) const char *SPATH = PATH.c_str()
bool wchartoutf8(const wchar_t *in, std::string& out, size_t len = 0);
std::string wchartoutf8(const wchar_t *in, size_t len = 0);
bool utf8towchar(const std::string& in, wchar_t *out, size_t obytescap);
std::unique_ptr<wchar_t[]> utf8towchar(const std::string& in);
#endif
/// Directory reading interface. UTF-8 on Windows.

View File

@ -32,7 +32,6 @@
#include "safefcntl.h"
#include "safesysstat.h"
#include "safeunistd.h"
#include "transcode.h"
#define OPEN _wopen
#else
@ -333,7 +332,12 @@ public:
// If we have a file name, open it, else use stdin.
if (!m_fn.empty()) {
SYSPATH(m_fn, realpath);
#ifdef _WIN32
auto buf = utf8towchar(m_fn);
auto realpath = buf.get();
#else
auto realpath = m_fn.c_str();
#endif
fd = OPEN(realpath, O_RDONLY | O_BINARY);
if (fd < 0 || fstat(fd, &st) < 0) {
catstrerror(m_reason, "open/stat", errno);
@ -440,7 +444,12 @@ public:
if (m_fn.empty()) {
ret1 = mz_zip_reader_init_mem(&zip, m_data, m_cnt, 0);
} else {
SYSPATH(m_fn, realpath);
#ifdef _WIN32
auto buf = utf8towchar(m_fn);
auto realpath = buf.get();
#else
auto realpath = m_fn.c_str();
#endif
ret1 = mz_zip_reader_init_file(&zip, realpath, 0);
}
if (!ret1) {

View File

@ -793,9 +793,9 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
int flags = CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT;
// Create the child process.
LOGDEB("ExecCmd:startExec: cmdline [" << cmdline << "]\n");
SYSPATH(cmdline, wcmdline);
auto wcmdline = utf8towchar(cmdline);
bSuccess = CreateProcessW(NULL, // app name
wcmdline, // command line
wcmdline.get(), // command line
NULL, // process security attributes
NULL, // primary thread security attrs
TRUE, // handles are inherited