pathut: path_chdir, more error checking in conversions

This commit is contained in:
Jean-Francois Dockes 2020-06-02 08:56:02 +01:00
parent 7ccde15839
commit 0f8b53d43b
2 changed files with 39 additions and 17 deletions

View File

@ -75,10 +75,6 @@
#ifdef _WIN32 #ifdef _WIN32
#if !defined(S_IFLNK)
#define S_IFLNK 0
#endif
#ifndef _MSC_VER #ifndef _MSC_VER
#undef WINVER #undef WINVER
#define WINVER 0x0601 #define WINVER 0x0601
@ -98,6 +94,10 @@
#include <io.h> #include <io.h>
#include <sys/stat.h> #include <sys/stat.h>
#if !defined(S_IFLNK)
#define S_IFLNK 0
#endif
#ifndef S_ISDIR #ifndef S_ISDIR
# define S_ISDIR(ST_MODE) (((ST_MODE) & _S_IFMT) == _S_IFDIR) # define S_ISDIR(ST_MODE) (((ST_MODE) & _S_IFMT) == _S_IFDIR)
#endif #endif
@ -122,6 +122,7 @@
#define MKDIR(a,b) _wmkdir(a) #define MKDIR(a,b) _wmkdir(a)
#define OPEN ::_wopen #define OPEN ::_wopen
#define UNLINK _wunlink #define UNLINK _wunlink
#define CHDIR _wchdir
#define ftruncate _chsize_s #define ftruncate _chsize_s
@ -153,7 +154,8 @@
#define MKDIR(a,b) mkdir(a,b) #define MKDIR(a,b) mkdir(a,b)
#define O_BINARY 0 #define O_BINARY 0
#define OPEN ::open #define OPEN ::open
#define UNLINK unlink #define UNLINK ::unlink
#define CHDIR ::chdir
#endif /* !_WIN32 */ #endif /* !_WIN32 */
@ -161,29 +163,39 @@ using namespace std;
#ifdef _WIN32 #ifdef _WIN32
bool wchartoutf8(const wchar_t *in, std::string& out) std::string wchartoutf8(const wchar_t *in, size_t len)
{ {
// fprintf(stderr, "WCHARTOUTF8: in [%S]\n", in); std::string out;
wchartoutf8(in, out, len);
return out;
}
bool wchartoutf8(const wchar_t *in, std::string& out, size_t wlen)
{
LOGDEB1("WCHARTOUTF8: in [" << in << "]\n");
out.clear(); out.clear();
if (nullptr == in) { if (nullptr == in) {
return true; return true;
} }
size_t wlen = wcslen(in); if (wlen == 0) {
wlen = wcslen(in);
}
int flags = WC_ERR_INVALID_CHARS|WC_NO_BEST_FIT_CHARS;
int bytes = ::WideCharToMultiByte( int bytes = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, in, wlen, nullptr, 0, nullptr, nullptr); CP_UTF8, flags, in, wlen, nullptr, 0, nullptr, nullptr);
if (bytes <= 0) { if (bytes <= 0) {
std::cerr << "wchartoutf8: CONVERSION ERROR1\n"; LOGERR("wchartoutf8: conversion error1\n");
return false; return false;
} }
char *cp = (char *)malloc(bytes+1); char *cp = (char *)malloc(bytes+1);
if (nullptr == cp) { if (nullptr == cp) {
std::cerr << "wchartoutf8: MALLOC FAILED\n"; LOGERR("wchartoutf8: malloc failed\n");
return false; return false;
} }
bytes = ::WideCharToMultiByte( bytes = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, in, wlen, cp, bytes, nullptr, nullptr); CP_UTF8, flags, in, wlen, cp, bytes, nullptr, nullptr);
if (bytes <= 0) { if (bytes <= 0) {
std::cerr << "wchartoutf8: CONVERSION ERROR2\n"; LOGERR("wchartoutf8: CONVERSION ERROR2\n");
free(cp); free(cp);
return false; return false;
} }
@ -204,17 +216,17 @@ bool utf8towchar(const std::string& in, wchar_t *out, size_t obytescap)
int wcharcnt = MultiByteToWideChar( int wcharcnt = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, in.c_str(), in.size(), nullptr, 0); CP_UTF8, MB_ERR_INVALID_CHARS, in.c_str(), in.size(), nullptr, 0);
if (wcharcnt <= 0) { if (wcharcnt <= 0) {
std::cerr << "utf8towchar: CONVERSION ERROR\n"; LOGERR("utf8towchar: conversion error for [" << in << "]\n");
return false; return false;
} }
if (wcharcnt + 1 > int(wcharsavail)) { if (wcharcnt + 1 > int(wcharsavail)) {
std::cerr << "utf8towchar: NOT ENOUGH SPACE\n"; LOGERR("utf8towchar: not enough space\n");
return false; return false;
} }
wcharcnt = MultiByteToWideChar( wcharcnt = MultiByteToWideChar(
CP_UTF8, MB_ERR_INVALID_CHARS, in.c_str(), in.size(), out, wcharsavail); CP_UTF8, MB_ERR_INVALID_CHARS, in.c_str(), in.size(), out, wcharsavail);
if (wcharcnt <= 0) { if (wcharcnt <= 0) {
std::cerr << "utf8towchar: CONVERSION ERROR\n"; LOGERR("utf8towchar: conversion error for [" << in << "]\n");
return false; return false;
} }
out[wcharcnt] = 0; out[wcharcnt] = 0;
@ -836,6 +848,12 @@ bool path_makepath(const string& ipath, int mode)
return true; return true;
} }
bool path_chdir(const std::string& path)
{
SYSPATH(path, syspath);
return CHDIR(syspath) == 0;
}
#if !defined(__GNUC__) || __GNUC__ > 4 || defined(__clang__) #if !defined(__GNUC__) || __GNUC__ > 4 || defined(__clang__)
// Not sure what g++ version supports fstream assignment but 4.9 // Not sure what g++ version supports fstream assignment but 4.9
// (jessie) certainly does not // (jessie) certainly does not

View File

@ -109,7 +109,8 @@ extern bool path_readable(const std::string& path);
extern std::string path_PATHsep(); extern std::string path_PATHsep();
#ifdef _WIN32 #ifdef _WIN32
extern bool wchartoutf8(const wchar_t *in, std::string& out); 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); extern bool utf8towchar(const std::string& in, wchar_t *out, size_t obytescap);
#define SYSPATH(PATH, SPATH) wchar_t PATH ## _buf[2048]; \ #define SYSPATH(PATH, SPATH) wchar_t PATH ## _buf[2048]; \
utf8towchar(PATH, PATH ## _buf, 2048); \ utf8towchar(PATH, PATH ## _buf, 2048); \
@ -132,6 +133,9 @@ bool fsocc(const std::string& path, int *pc, long long *avmbs = 0);
/// mkdir -p /// mkdir -p
extern bool path_makepath(const std::string& path, int mode); extern bool path_makepath(const std::string& path, int mode);
///
extern bool path_chdir(const std::string& path);
/* Open file, trying to do the right thing with non-ASCII paths on /* Open file, trying to do the right thing with non-ASCII paths on
* Windows, where it only works with MSVC at the moment if the path is * Windows, where it only works with MSVC at the moment if the path is
* not ASCII, because it uses fstream(wchar_t*), which is an MSVC * not ASCII, because it uses fstream(wchar_t*), which is an MSVC