1
0
Fork 0

Feature/windows utf16 fileaccess (#6534)

This commit is contained in:
Wilfried Goesgens 2018-09-24 19:41:17 +02:00 committed by Jan
parent f63fedf139
commit a477df49cf
33 changed files with 735 additions and 271 deletions

View File

@ -38,6 +38,7 @@ if (MSVC)
set(SNAPPY_INCLUDE "${SNAPPY_INCLUDE_DIR}" CACHE PATH "where the wintendo should look for the snappy libs") set(SNAPPY_INCLUDE "${SNAPPY_INCLUDE_DIR}" CACHE PATH "where the wintendo should look for the snappy libs")
set(SNAPPY_LIB_DEBUG "${CMAKE_BINARY_DIR}/bin/Debug/${SNAPPY_LIB}.lib") set(SNAPPY_LIB_DEBUG "${CMAKE_BINARY_DIR}/bin/Debug/${SNAPPY_LIB}.lib")
set(SNAPPY_LIB_RELEASE "${CMAKE_BINARY_DIR}/bin/RelWithDebInfo/${SNAPPY_LIB}.lib") set(SNAPPY_LIB_RELEASE "${CMAKE_BINARY_DIR}/bin/RelWithDebInfo/${SNAPPY_LIB}.lib")
set(WITH_WINDOWS_UTF8_FILENAMES ON CACHE BOOL "we want to provide utf8 filenames")
endif () endif ()
set(USE_RTTI ON CACHE BOOL "enable RTTI") set(USE_RTTI ON CACHE BOOL "enable RTTI")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${ARANGO_ROCKSDB_VERSION} EXCLUDE_FROM_ALL) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${ARANGO_ROCKSDB_VERSION} EXCLUDE_FROM_ALL)

View File

@ -49,6 +49,10 @@ option(WITH_SNAPPY "build with SNAPPY" OFF)
option(WITH_LZ4 "build with lz4" OFF) option(WITH_LZ4 "build with lz4" OFF)
option(WITH_ZLIB "build with zlib" OFF) option(WITH_ZLIB "build with zlib" OFF)
option(WITH_ZSTD "build with zstd" OFF) option(WITH_ZSTD "build with zstd" OFF)
option(WITH_WINDOWS_UTF8_FILENAMES "use UTF8 as characterset for opening files, regardles of the system code page" OFF)
if (WITH_WINDOWS_UTF8_FILENAMES)
add_definitions(-DROCKSDB_WINDOWS_UTF8_FILENAMES)
endif()
if(MSVC) if(MSVC)
# Defaults currently different for GFLAGS. # Defaults currently different for GFLAGS.
# We will address find_package work a little later # We will address find_package work a little later

View File

@ -102,7 +102,8 @@ WinEnvIO::~WinEnvIO() {
Status WinEnvIO::DeleteFile(const std::string& fname) { Status WinEnvIO::DeleteFile(const std::string& fname) {
Status result; Status result;
BOOL ret = DeleteFileA(fname.c_str()); BOOL ret = RX_DeleteFile(RX_FN(fname).c_str());
if(!ret) { if(!ret) {
auto lastError = GetLastError(); auto lastError = GetLastError();
result = IOErrorFromWindowsError("Failed to delete: " + fname, result = IOErrorFromWindowsError("Failed to delete: " + fname,
@ -114,7 +115,7 @@ Status WinEnvIO::DeleteFile(const std::string& fname) {
Status WinEnvIO::Truncate(const std::string& fname, size_t size) { Status WinEnvIO::Truncate(const std::string& fname, size_t size) {
Status s; Status s;
int result = truncate(fname.c_str(), size); int result = rocksdb::port::Truncate(fname, size);
if (result != 0) { if (result != 0) {
s = IOError("Failed to truncate: " + fname, errno); s = IOError("Failed to truncate: " + fname, errno);
} }
@ -151,8 +152,8 @@ Status WinEnvIO::NewSequentialFile(const std::string& fname,
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA( hFile = RX_CreateFile(
fname.c_str(), GENERIC_READ, RX_FN(fname).c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, // Original fopen mode is "rb" OPEN_EXISTING, // Original fopen mode is "rb"
fileFlags, NULL); fileFlags, NULL);
@ -190,7 +191,7 @@ Status WinEnvIO::NewRandomAccessFile(const std::string& fname,
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
hFile = hFile =
CreateFileA(fname.c_str(), GENERIC_READ, RX_CreateFile(RX_FN(fname).c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, fileFlags, NULL); NULL, OPEN_EXISTING, fileFlags, NULL);
} }
@ -217,7 +218,7 @@ Status WinEnvIO::NewRandomAccessFile(const std::string& fname,
"NewRandomAccessFile failed to map empty file: " + fname, EINVAL); "NewRandomAccessFile failed to map empty file: " + fname, EINVAL);
} }
HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, HANDLE hMap = RX_CreateFileMapping(hFile, NULL, PAGE_READONLY,
0, // Whole file at its present length 0, // Whole file at its present length
0, 0,
NULL); // Mapping name NULL); // Mapping name
@ -302,8 +303,8 @@ Status WinEnvIO::OpenWritableFile(const std::string& fname,
HANDLE hFile = 0; HANDLE hFile = 0;
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA( hFile = RX_CreateFile(
fname.c_str(), RX_FN(fname).c_str(),
desired_access, // Access desired desired_access, // Access desired
shared_mode, shared_mode,
NULL, // Security attributes NULL, // Security attributes
@ -366,7 +367,7 @@ Status WinEnvIO::NewRandomRWFile(const std::string & fname,
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
hFile = hFile =
CreateFileA(fname.c_str(), RX_CreateFile(RX_FN(fname).c_str(),
desired_access, desired_access,
shared_mode, shared_mode,
NULL, // Security attributes NULL, // Security attributes
@ -399,8 +400,8 @@ Status WinEnvIO::NewMemoryMappedFileBuffer(const std::string & fname,
HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hFile = INVALID_HANDLE_VALUE;
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA( hFile = RX_CreateFile(
fname.c_str(), GENERIC_READ | GENERIC_WRITE, RX_FN(fname).c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, NULL,
OPEN_EXISTING, // Open only if it exists OPEN_EXISTING, // Open only if it exists
@ -432,7 +433,7 @@ Status WinEnvIO::NewMemoryMappedFileBuffer(const std::string & fname,
"The specified file size does not fit into 32-bit memory addressing: " + fname); "The specified file size does not fit into 32-bit memory addressing: " + fname);
} }
HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, HANDLE hMap = RX_CreateFileMapping(hFile, NULL, PAGE_READWRITE,
0, // Whole file at its present length 0, // Whole file at its present length
0, 0,
NULL); // Mapping name NULL); // Mapping name
@ -483,7 +484,7 @@ Status WinEnvIO::NewDirectory(const std::string& name,
// 0 - for access means read metadata // 0 - for access means read metadata
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
handle = ::CreateFileA(name.c_str(), 0, handle = RX_CreateFile(RX_FN(name).c_str(), 0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, NULL,
OPEN_EXISTING, OPEN_EXISTING,
@ -509,8 +510,7 @@ Status WinEnvIO::FileExists(const std::string& fname) {
// which is consistent with _access() impl on windows // which is consistent with _access() impl on windows
// but can be added // but can be added
WIN32_FILE_ATTRIBUTE_DATA attrs; WIN32_FILE_ATTRIBUTE_DATA attrs;
if (FALSE == GetFileAttributesExA(fname.c_str(), GetFileExInfoStandard, if (FALSE == RX_GetFileAttributesEx(RX_FN(fname).c_str(), GetFileExInfoStandard, &attrs)) {
&attrs)) {
auto lastError = GetLastError(); auto lastError = GetLastError();
switch (lastError) { switch (lastError) {
case ERROR_ACCESS_DENIED: case ERROR_ACCESS_DENIED:
@ -535,11 +535,12 @@ Status WinEnvIO::GetChildren(const std::string& dir,
result->clear(); result->clear();
std::vector<std::string> output; std::vector<std::string> output;
WIN32_FIND_DATA data; RX_WIN32_FIND_DATA data;
memset(&data, 0, sizeof(data));
std::string pattern(dir); std::string pattern(dir);
pattern.append("\\").append("*"); pattern.append("\\").append("*");
HANDLE handle = ::FindFirstFileExA(pattern.c_str(), HANDLE handle = RX_FindFirstFileEx(RX_FN(pattern).c_str(),
FindExInfoBasic, // Do not want alternative name FindExInfoBasic, // Do not want alternative name
&data, &data,
FindExSearchNameMatch, FindExSearchNameMatch,
@ -572,8 +573,9 @@ Status WinEnvIO::GetChildren(const std::string& dir,
data.cFileName[MAX_PATH - 1] = 0; data.cFileName[MAX_PATH - 1] = 0;
while (true) { while (true) {
output.emplace_back(data.cFileName); auto x = RX_FILESTRING(data.cFileName, RX_FNLEN(data.cFileName));
BOOL ret =- ::FindNextFileA(handle, &data); output.emplace_back(FN_TO_RX(x));
BOOL ret =- RX_FindNextFile(handle, &data);
// If the function fails the return value is zero // If the function fails the return value is zero
// and non-zero otherwise. Not TRUE or FALSE. // and non-zero otherwise. Not TRUE or FALSE.
if (ret == FALSE) { if (ret == FALSE) {
@ -588,8 +590,7 @@ Status WinEnvIO::GetChildren(const std::string& dir,
Status WinEnvIO::CreateDir(const std::string& name) { Status WinEnvIO::CreateDir(const std::string& name) {
Status result; Status result;
BOOL ret = RX_CreateDirectory(RX_FN(name).c_str(), NULL);
BOOL ret = CreateDirectoryA(name.c_str(), NULL);
if (!ret) { if (!ret) {
auto lastError = GetLastError(); auto lastError = GetLastError();
result = IOErrorFromWindowsError( result = IOErrorFromWindowsError(
@ -606,7 +607,7 @@ Status WinEnvIO::CreateDirIfMissing(const std::string& name) {
return result; return result;
} }
BOOL ret = CreateDirectoryA(name.c_str(), NULL); BOOL ret = RX_CreateDirectory(RX_FN(name).c_str(), NULL);
if (!ret) { if (!ret) {
auto lastError = GetLastError(); auto lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS) { if (lastError != ERROR_ALREADY_EXISTS) {
@ -622,7 +623,7 @@ Status WinEnvIO::CreateDirIfMissing(const std::string& name) {
Status WinEnvIO::DeleteDir(const std::string& name) { Status WinEnvIO::DeleteDir(const std::string& name) {
Status result; Status result;
BOOL ret = RemoveDirectoryA(name.c_str()); BOOL ret = RX_RemoveDirectory(RX_FN(name).c_str());
if (!ret) { if (!ret) {
auto lastError = GetLastError(); auto lastError = GetLastError();
result = IOErrorFromWindowsError("Failed to remove dir: " + name, lastError); result = IOErrorFromWindowsError("Failed to remove dir: " + name, lastError);
@ -635,7 +636,7 @@ Status WinEnvIO::GetFileSize(const std::string& fname,
Status s; Status s;
WIN32_FILE_ATTRIBUTE_DATA attrs; WIN32_FILE_ATTRIBUTE_DATA attrs;
if (GetFileAttributesExA(fname.c_str(), GetFileExInfoStandard, &attrs)) { if (RX_GetFileAttributesEx(RX_FN(fname).c_str(), GetFileExInfoStandard, &attrs)) {
ULARGE_INTEGER file_size; ULARGE_INTEGER file_size;
file_size.HighPart = attrs.nFileSizeHigh; file_size.HighPart = attrs.nFileSizeHigh;
file_size.LowPart = attrs.nFileSizeLow; file_size.LowPart = attrs.nFileSizeLow;
@ -670,7 +671,7 @@ Status WinEnvIO::GetFileModificationTime(const std::string& fname,
Status s; Status s;
WIN32_FILE_ATTRIBUTE_DATA attrs; WIN32_FILE_ATTRIBUTE_DATA attrs;
if (GetFileAttributesExA(fname.c_str(), GetFileExInfoStandard, &attrs)) { if (RX_GetFileAttributesEx(RX_FN(fname).c_str(), GetFileExInfoStandard, &attrs)) {
*file_mtime = FileTimeToUnixTime(attrs.ftLastWriteTime); *file_mtime = FileTimeToUnixTime(attrs.ftLastWriteTime);
} else { } else {
auto lastError = GetLastError(); auto lastError = GetLastError();
@ -688,7 +689,7 @@ Status WinEnvIO::RenameFile(const std::string& src,
// rename() is not capable of replacing the existing file as on Linux // rename() is not capable of replacing the existing file as on Linux
// so use OS API directly // so use OS API directly
if (!MoveFileExA(src.c_str(), target.c_str(), MOVEFILE_REPLACE_EXISTING)) { if (!RX_MoveFileEx(RX_FN(src).c_str(), RX_FN(target).c_str(), MOVEFILE_REPLACE_EXISTING)) {
DWORD lastError = GetLastError(); DWORD lastError = GetLastError();
std::string text("Failed to rename: "); std::string text("Failed to rename: ");
@ -704,7 +705,7 @@ Status WinEnvIO::LinkFile(const std::string& src,
const std::string& target) { const std::string& target) {
Status result; Status result;
if (!CreateHardLinkA(target.c_str(), src.c_str(), NULL)) { if (!RX_CreateHardLink(RX_FN(target).c_str(), RX_FN(src).c_str(), NULL)) {
DWORD lastError = GetLastError(); DWORD lastError = GetLastError();
std::string text("Failed to link: "); std::string text("Failed to link: ");
@ -719,7 +720,7 @@ Status WinEnvIO::LinkFile(const std::string& src,
Status WinEnvIO::NumFileLinks(const std::string& fname, Status WinEnvIO::NumFileLinks(const std::string& fname,
uint64_t* count) { uint64_t* count) {
Status s; Status s;
HANDLE handle = ::CreateFileA(fname.c_str(), 0, HANDLE handle = RX_CreateFile(RX_FN(fname).c_str(), 0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, NULL,
OPEN_EXISTING, OPEN_EXISTING,
@ -758,7 +759,7 @@ Status WinEnvIO::AreFilesSame(const std::string& first,
} }
// 0 - for access means read metadata // 0 - for access means read metadata
HANDLE file_1 = ::CreateFileA(first.c_str(), 0, HANDLE file_1 = RX_CreateFile(RX_FN(first).c_str(), 0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, NULL,
OPEN_EXISTING, OPEN_EXISTING,
@ -773,7 +774,7 @@ Status WinEnvIO::AreFilesSame(const std::string& first,
} }
UniqueCloseHandlePtr g_1(file_1, CloseHandleFunc); UniqueCloseHandlePtr g_1(file_1, CloseHandleFunc);
HANDLE file_2 = ::CreateFileA(second.c_str(), 0, HANDLE file_2 = RX_CreateFile(RX_FN(second).c_str(), 0,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, // make opening folders possible FILE_FLAG_BACKUP_SEMANTICS, // make opening folders possible
@ -835,7 +836,7 @@ Status WinEnvIO::LockFile(const std::string& lockFname,
HANDLE hFile = 0; HANDLE hFile = 0;
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA(lockFname.c_str(), (GENERIC_READ | GENERIC_WRITE), hFile = RX_CreateFile(RX_FN(lockFname).c_str(), (GENERIC_READ | GENERIC_WRITE),
ExclusiveAccessON, NULL, CREATE_ALWAYS, ExclusiveAccessON, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL); FILE_ATTRIBUTE_NORMAL, NULL);
} }
@ -898,8 +899,8 @@ Status WinEnvIO::NewLogger(const std::string& fname,
HANDLE hFile = 0; HANDLE hFile = 0;
{ {
IOSTATS_TIMER_GUARD(open_nanos); IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA( hFile = RX_CreateFile(
fname.c_str(), GENERIC_WRITE, RX_FN(fname).c_str(), GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_DELETE, // In RocksDb log files are FILE_SHARE_READ | FILE_SHARE_DELETE, // In RocksDb log files are
// renamed and deleted before // renamed and deleted before
// they are closed. This enables // they are closed. This enables
@ -992,17 +993,17 @@ Status WinEnvIO::GetAbsolutePath(const std::string& db_path,
// For test compatibility we will consider starting slash as an // For test compatibility we will consider starting slash as an
// absolute path // absolute path
if ((!db_path.empty() && (db_path[0] == '\\' || db_path[0] == '/')) || if ((!db_path.empty() && (db_path[0] == '\\' || db_path[0] == '/')) ||
!PathIsRelativeA(db_path.c_str())) { !RX_PathIsRelative(RX_FN(db_path).c_str())) {
*output_path = db_path; *output_path = db_path;
return Status::OK(); return Status::OK();
} }
std::string result; RX_FILESTRING result;
result.resize(MAX_PATH); result.resize(MAX_PATH);
// Hopefully no changes the current directory while we do this // Hopefully no changes the current directory while we do this
// however _getcwd also suffers from the same limitation // however _getcwd also suffers from the same limitation
DWORD len = GetCurrentDirectoryA(MAX_PATH, &result[0]); DWORD len = RX_GetCurrentDirectory(MAX_PATH, &result[0]);
if (len == 0) { if (len == 0) {
auto lastError = GetLastError(); auto lastError = GetLastError();
return IOErrorFromWindowsError("Failed to get current working directory", return IOErrorFromWindowsError("Failed to get current working directory",
@ -1010,8 +1011,9 @@ Status WinEnvIO::GetAbsolutePath(const std::string& db_path,
} }
result.resize(len); result.resize(len);
std::string res = FN_TO_RX(result);
result.swap(*output_path); res.swap(*output_path);
return Status::OK(); return Status::OK();
} }
@ -1076,7 +1078,7 @@ EnvOptions WinEnvIO::OptimizeForManifestRead(
// Returns true iff the named directory exists and is a directory. // Returns true iff the named directory exists and is a directory.
bool WinEnvIO::DirExists(const std::string& dname) { bool WinEnvIO::DirExists(const std::string& dname) {
WIN32_FILE_ATTRIBUTE_DATA attrs; WIN32_FILE_ATTRIBUTE_DATA attrs;
if (GetFileAttributesExA(dname.c_str(), GetFileExInfoStandard, &attrs)) { if (RX_GetFileAttributesEx(RX_FN(dname).c_str(), GetFileExInfoStandard, &attrs)) {
return 0 != (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); return 0 != (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
} }
return false; return false;
@ -1085,7 +1087,7 @@ bool WinEnvIO::DirExists(const std::string& dname) {
size_t WinEnvIO::GetSectorSize(const std::string& fname) { size_t WinEnvIO::GetSectorSize(const std::string& fname) {
size_t sector_size = kSectorSize; size_t sector_size = kSectorSize;
if (PathIsRelativeA(fname.c_str())) { if (RX_PathIsRelative(RX_FN(fname).c_str())) {
return sector_size; return sector_size;
} }

View File

@ -26,11 +26,28 @@
#include <exception> #include <exception>
#include <chrono> #include <chrono>
#ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
// utf8 <-> utf16
#include <string>
#include <locale>
#include <codecvt>
#endif
#include "util/logging.h" #include "util/logging.h"
namespace rocksdb { namespace rocksdb {
namespace port { namespace port {
std::string utf16_to_utf8(const std::wstring& utf16) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert;
return convert.to_bytes(utf16);
}
std::wstring utf8_to_utf16(const std::string& utf8) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(utf8);
}
void gettimeofday(struct timeval* tv, struct timezone* /* tz */) { void gettimeofday(struct timeval* tv, struct timezone* /* tz */) {
using namespace std::chrono; using namespace std::chrono;
@ -110,7 +127,7 @@ void InitOnce(OnceType* once, void (*initializer)()) {
struct DIR { struct DIR {
HANDLE handle_; HANDLE handle_;
bool firstread_; bool firstread_;
WIN32_FIND_DATA data_; RX_WIN32_FIND_DATA data_;
dirent entry_; dirent entry_;
DIR() : handle_(INVALID_HANDLE_VALUE), DIR() : handle_(INVALID_HANDLE_VALUE),
@ -137,7 +154,7 @@ DIR* opendir(const char* name) {
std::unique_ptr<DIR> dir(new DIR); std::unique_ptr<DIR> dir(new DIR);
dir->handle_ = ::FindFirstFileExA(pattern.c_str(), dir->handle_ = RX_FindFirstFileEx(RX_FN(pattern).c_str(),
FindExInfoBasic, // Do not want alternative name FindExInfoBasic, // Do not want alternative name
&dir->data_, &dir->data_,
FindExSearchNameMatch, FindExSearchNameMatch,
@ -148,8 +165,9 @@ DIR* opendir(const char* name) {
return nullptr; return nullptr;
} }
RX_FILESTRING x(dir->data_.cFileName, RX_FNLEN(dir->data_.cFileName));
strcpy_s(dir->entry_.d_name, sizeof(dir->entry_.d_name), strcpy_s(dir->entry_.d_name, sizeof(dir->entry_.d_name),
dir->data_.cFileName); FN_TO_RX(x).c_str());
return dir.release(); return dir.release();
} }
@ -165,14 +183,15 @@ struct dirent* readdir(DIR* dirp) {
return &dirp->entry_; return &dirp->entry_;
} }
auto ret = ::FindNextFileA(dirp->handle_, &dirp->data_); auto ret = RX_FindNextFile(dirp->handle_, &dirp->data_);
if (ret == 0) { if (ret == 0) {
return nullptr; return nullptr;
} }
RX_FILESTRING x(dirp->data_.cFileName, RX_FNLEN(dirp->data_.cFileName));
strcpy_s(dirp->entry_.d_name, sizeof(dirp->entry_.d_name), strcpy_s(dirp->entry_.d_name, sizeof(dirp->entry_.d_name),
dirp->data_.cFileName); FN_TO_RX(x).c_str());
return &dirp->entry_; return &dirp->entry_;
} }
@ -182,11 +201,15 @@ int closedir(DIR* dirp) {
return 0; return 0;
} }
int truncate(const char* path, int64_t len) { int truncate(const char* path, int64_t length) {
if (path == nullptr) { if (path == nullptr) {
errno = EFAULT; errno = EFAULT;
return -1; return -1;
} }
return rocksdb::port::Truncate(path, length);
}
int Truncate(std::string path, int64_t len) {
if (len < 0) { if (len < 0) {
errno = EINVAL; errno = EINVAL;
@ -194,7 +217,7 @@ int truncate(const char* path, int64_t len) {
} }
HANDLE hFile = HANDLE hFile =
CreateFile(path, GENERIC_READ | GENERIC_WRITE, RX_CreateFile(RX_FN(path).c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, // Security attrs NULL, // Security attrs
OPEN_EXISTING, // Truncate existing file only OPEN_EXISTING, // Truncate existing file only

View File

@ -328,11 +328,62 @@ inline void* pthread_getspecific(pthread_key_t key) {
// using C-runtime to implement. Note, this does not // using C-runtime to implement. Note, this does not
// feel space with zeros in case the file is extended. // feel space with zeros in case the file is extended.
int truncate(const char* path, int64_t length); int truncate(const char* path, int64_t length);
int Truncate(std::string path, int64_t length);
void Crash(const std::string& srcfile, int srcline); void Crash(const std::string& srcfile, int srcline);
extern int GetMaxOpenFiles(); extern int GetMaxOpenFiles();
std::string utf16_to_utf8(const std::wstring& utf16);
std::wstring utf8_to_utf16(const std::string& utf8);
} // namespace port } // namespace port
#ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
#define RX_FILESTRING std::wstring
#define RX_FN(a) rocksdb::port::utf8_to_utf16(a)
#define FN_TO_RX(a) rocksdb::port::utf16_to_utf8(a)
#define RX_FNLEN(a) ::wcslen(a)
#define RX_DeleteFile DeleteFileW
#define RX_CreateFile CreateFileW
#define RX_CreateFileMapping CreateFileMappingW
#define RX_GetFileAttributesEx GetFileAttributesExW
#define RX_FindFirstFileEx FindFirstFileExW
#define RX_FindNextFile FindNextFileW
#define RX_WIN32_FIND_DATA WIN32_FIND_DATAW
#define RX_CreateDirectory CreateDirectoryW
#define RX_RemoveDirectory RemoveDirectoryW
#define RX_GetFileAttributesEx GetFileAttributesExW
#define RX_MoveFileEx MoveFileExW
#define RX_CreateHardLink CreateHardLinkW
#define RX_PathIsRelative PathIsRelativeW
#define RX_GetCurrentDirectory GetCurrentDirectoryW
#else
#define RX_FILESTRING std::string
#define RX_FN(a) a
#define FN_TO_RX(a) a
#define RX_FNLEN(a) strlen(a)
#define RX_DeleteFile DeleteFileA
#define RX_CreateFile CreateFileA
#define RX_CreateFileMapping CreateFileMappingA
#define RX_GetFileAttributesEx GetFileAttributesExA
#define RX_FindFirstFileEx FindFirstFileExA
#define RX_CreateDirectory CreateDirectoryA
#define RX_FindNextFile FindNextFileA
#define RX_WIN32_FIND_DATA WIN32_FIND_DATA
#define RX_CreateDirectory CreateDirectoryA
#define RX_RemoveDirectory RemoveDirectoryA
#define RX_GetFileAttributesEx GetFileAttributesExA
#define RX_MoveFileEx MoveFileExA
#define RX_CreateHardLink CreateHardLinkA
#define RX_PathIsRelative PathIsRelativeA
#define RX_GetCurrentDirectory GetCurrentDirectoryA
#endif
using port::pthread_key_t; using port::pthread_key_t;
using port::pthread_key_create; using port::pthread_key_create;
using port::pthread_key_delete; using port::pthread_key_delete;

View File

@ -0,0 +1,120 @@
/**
* Two macroses to convert ANSI text to UTF-8 and conversely.
* This file is FREE FOR USE.
*
* Written by Shurmialiou Vadzim at 04/2010
* inshae@gmail.com
*/
!ifndef ___ANSITOUTF8_NSH___
!define ___ANSITOUTF8_NSH___
!include "LogicLib.nsh"
/**
* Convert ANSI text to UTF-8 text in the installer or uninstaller.
*
* Usage:
* StrCpy $0 "Belarussian text: ПрÑвiÑанне, Свет!"
* ${AnsiToUtf8} $0 $1
* DetailPrint "'$1' == 'Belarussian text: Прывiтанне, Свет!'" ;UTF-8 text
*/
!define AnsiToUtf8 '!insertmacro AnsiToUtf8Macro'
!macro AnsiToUtf8Macro SOURCE_STRING OUTPUT_STRING
Push "${SOURCE_STRING}"
Push 0 ;ANSI codepage
Push 65001 ;UTF-8 codepage
!insertmacro ConvertOverUnicode
Pop "${OUTPUT_STRING}"
!macroend
/**
* Convert UTF-8 text to ANSI text in the installer or uninstaller.
*
* Usage:
* StrCpy $0 "Belarussian text: Прывiтанне, Свет!"
* ${Utf8ToAnsi} $0 $1
* DetailPrint "'$1' == 'Belarussian text: ПрÑвiÑанне, Свет!'" ;UTF-8 text
*/
!define Utf8ToAnsi '!insertmacro Utf8ToAnsiMacro'
!macro Utf8ToAnsiMacro SOURCE_STRING OUTPUT_STRING
Push "${SOURCE_STRING}"
Push 65001 ;UTF-8 codepage
Push 0 ;ANSI codepage
!insertmacro ConvertOverUnicode
Pop "${OUTPUT_STRING}"
!macroend
!macro ConvertOverUnicode
Exch $0 ;Result codepage
Exch
Exch $1 ;Source codepage
Exch
Exch 2
Exch $2 ;Source text
Push $3 ;Result text
Push $4
Push $5 ;unicode text
Push $6
Push $7
Push $8
StrCpy $3 ""
;From ANSI to Unicode and then from unicode to UTF-8
${If} $2 != ""
;long bufSize = ::MultiByteToWideChar(CP_ACP, 0, cp1251str, -1, 0, 0);
System::Call /NOUNLOAD "kernel32::MultiByteToWideChar(i r1, i 0, t r2, i -1, i 0, i 0) i .r4"
${If} $4 > 0
IntOp $4 $4 * 2 ;2 bytes by one unicode-symbol
System::Alloc /NOUNLOAD $4
Pop $5
; ::MultiByteToWideChar(CP_ACP, 0, cp1251str, -1, unicodeStr, bufSize)
System::Call /NOUNLOAD "kernel32::MultiByteToWideChar(i r1, i 0, t r2, i -1, i r5, i r4) i .r6"
${If} $6 > 0
;bufSize = ::WideCharToMultiByte(CP_UTF8, 0, unicodeStr, -1, 0, 0, 0, 0);
System::Call /NOUNLOAD "kernel32::WideCharToMultiByte(i r0, i 0, i r5, i -1, i 0, i 0, i 0, i 0) i .r6"
; ::WideCharToMultiByte(CP_UTF8, 0, unicodeStr, -1, utf8Str, bufSize, 0, 0)
System::Call /NOUNLOAD "kernel32::WideCharToMultiByte(i r0, i 0, i r5, i -1, t .r7, i r6, i 0, i 0) i .r8"
${If} $8 > 0
;Save result to $3
StrCpy $3 $7
${EndIf}
${EndIf}
;Free buffer from unicode string
System::Free $5
${EndIf}
${EndIf}
Pop $8
Pop $7
Pop $6
Pop $5
Pop $4
Exch
Pop $2
Exch
Pop $1
Exch
Pop $0
Exch $3
!macroend
!endif ;___ANSITOUTF8_NSH___

View File

@ -15,6 +15,7 @@
!include "MUI2.nsh" !include "MUI2.nsh"
!include "StripSlashes.nsh" !include "StripSlashes.nsh"
!include "xcopy.nsh" !include "xcopy.nsh"
!include "Utf8Converter.nsh"
; !include "GetTime.nsh" ; !include "GetTime.nsh"
;-------------------------------- ;--------------------------------
; get commandline parameters ; get commandline parameters
@ -67,6 +68,7 @@ Var BackupPath
VAR TRI_INSTALL_SERVICE ; x bool VAR TRI_INSTALL_SERVICE ; x bool
VAR TRI_INSTALL_SCOPE_ALL ; x bool => All / ThisUser VAR TRI_INSTALL_SCOPE_ALL ; x bool => All / ThisUser
Var newCfgValues ; keep new config file values Var newCfgValues ; keep new config file values
Var newCfgValuesUtf8 ; translated version of the content
Var newCfgValuesFile ; write them to a temporary file... Var newCfgValuesFile ; write them to a temporary file...
Var ServiceUp ; did the service start? Var ServiceUp ; did the service start?
!define TEMP1 $R0 ;Temp variable !define TEMP1 $R0 ;Temp variable
@ -207,8 +209,10 @@ Function un.ReadSettings
;MessageBox MB_OK "Add to path: $ADD_TO_PATH" ;MessageBox MB_OK "Add to path: $ADD_TO_PATH"
ReadRegStr $ADD_DESKTOP_ICON SHCTX "${TRI_UNINSTALL_REG_PATH}" "InstallToDesktop" ReadRegStr $ADD_DESKTOP_ICON SHCTX "${TRI_UNINSTALL_REG_PATH}" "InstallToDesktop"
ReadINIStr $DATADIR "$INSTDIR\${ARANGO_INI}" "database" "directory" ReadINIStr $newCfgValuesUtf8 "$INSTDIR\${ARANGO_INI}" "database" "directory"
ReadINIStr $APPDIR "$INSTDIR\${ARANGO_INI}" "javascript" "app-path" ${Utf8ToAnsi} $newCfgValuesUtf8 $DATADIR
ReadINIStr $newCfgValuesUtf8 "$INSTDIR\${ARANGO_INI}" "javascript" "app-path"
${Utf8ToAnsi} $newCfgValuesUtf8 $APPDIR
FunctionEnd FunctionEnd
@ -948,9 +952,10 @@ Section "-Core installation"
; StrCpy $ini_LOGFILE "[log]$\r$\nfile = $LOGFILE$\r$\n" ; StrCpy $ini_LOGFILE "[log]$\r$\nfile = $LOGFILE$\r$\n"
;${EndIf} ;${EndIf}
StrCpy $newCfgValues "$ini_APPDIR$ini_DATADIR[server]$\r$\nstorage-engine = $STORAGE_ENGINE$\r$\n" StrCpy $newCfgValues "$ini_APPDIR$ini_DATADIR[server]$\r$\nstorage-engine = $STORAGE_ENGINE$\r$\n"
${AnsiToUtf8} $newCfgValues $newCfgValuesUtf8
StrCpy $newCfgValuesFile "$INSTDIR\etc\arangodb3\newValues.ini" StrCpy $newCfgValuesFile "$INSTDIR\etc\arangodb3\newValues.ini"
FileOpen $4 "$newCfgValuesFile" w FileOpen $4 "$newCfgValuesFile" w
FileWrite $4 "$newCfgValues" FileWrite $4 "$newCfgValuesUtf8"
FileClose $4 FileClose $4
; Alter the shipped file and insert the values from above: ; Alter the shipped file and insert the values from above:
push "$newCfgValuesFile" push "$newCfgValuesFile"

View File

@ -24,8 +24,6 @@
#include "ServerState.h" #include "ServerState.h"
#include <iomanip> #include <iomanip>
#include <iostream>
#include <sstream>
#include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp> #include <boost/uuid/uuid_generators.hpp>
@ -451,19 +449,24 @@ std::string ServerState::generatePersistedId(RoleEnum const& role) {
} }
std::string ServerState::getPersistedId() { std::string ServerState::getPersistedId() {
if (hasPersistedId()) {
std::string uuidFilename = getUuidFilename(); std::string uuidFilename = getUuidFilename();
std::ifstream ifs(uuidFilename); if (hasPersistedId()) {
try {
std::string id; auto uuidBuf = arangodb::basics::FileUtils::slurp(uuidFilename);
if (ifs.is_open()) { basics::StringUtils::trimInPlace(uuidBuf);
std::getline(ifs, id); if (!uuidBuf.empty()) {
ifs.close(); return uuidBuf;
return id; }
}
catch (arangodb::basics::Exception const& ex) {
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "Couldn't read UUID file '"
<< uuidFilename << "' - "
<< ex.what();
FATAL_ERROR_EXIT();
} }
} }
LOG_TOPIC(FATAL, Logger::STARTUP) << "Couldn't open UUID file '" << getUuidFilename() << "'"; LOG_TOPIC(FATAL, Logger::STARTUP) << "Couldn't open UUID file '" << uuidFilename << "'";
FATAL_ERROR_EXIT(); FATAL_ERROR_EXIT();
} }

View File

@ -295,6 +295,7 @@ static void WINAPI ServiceMain(DWORD dwArgc, LPSTR* lpszArgv) {
// set start pending // set start pending
SetServiceStatus(SERVICE_START_PENDING, 0, 1, 10000, 0); SetServiceStatus(SERVICE_START_PENDING, 0, 1, 10000, 0);
TRI_GET_ARGV(ARGC, ARGV);
ArangoGlobalContext context(ARGC, ARGV, SBIN_DIRECTORY); ArangoGlobalContext context(ARGC, ARGV, SBIN_DIRECTORY);
runServer(ARGC, ARGV, context); runServer(ARGC, ARGV, context);
@ -306,6 +307,7 @@ static void WINAPI ServiceMain(DWORD dwArgc, LPSTR* lpszArgv) {
#endif #endif
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
#if _WIN32 #if _WIN32
if (argc > 1 && TRI_EqualString("--start-service", argv[1])) { if (argc > 1 && TRI_EqualString("--start-service", argv[1])) {
ARGC = argc; ARGC = argc;

View File

@ -45,6 +45,7 @@ using namespace arangodb::application_features;
using namespace arangodb::basics; using namespace arangodb::basics;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int { return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int {
ArangoGlobalContext context(argc, argv, BIN_DIRECTORY); ArangoGlobalContext context(argc, argv, BIN_DIRECTORY);
context.installHup(); context.installHup();

View File

@ -47,6 +47,7 @@ using namespace arangodb;
using namespace arangodb::application_features; using namespace arangodb::application_features;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int { return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int {
ArangoGlobalContext context(argc, argv, BIN_DIRECTORY); ArangoGlobalContext context(argc, argv, BIN_DIRECTORY);
context.installHup(); context.installHup();

View File

@ -44,6 +44,7 @@ using namespace arangodb;
using namespace arangodb::application_features; using namespace arangodb::application_features;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int { return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int {
ArangoGlobalContext context(argc, argv, BIN_DIRECTORY); ArangoGlobalContext context(argc, argv, BIN_DIRECTORY);
context.installHup(); context.installHup();

View File

@ -44,6 +44,7 @@ using namespace arangodb;
using namespace arangodb::application_features; using namespace arangodb::application_features;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int { return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int {
ArangoGlobalContext context(argc, argv, BIN_DIRECTORY); ArangoGlobalContext context(argc, argv, BIN_DIRECTORY);
context.installHup(); context.installHup();

View File

@ -47,6 +47,7 @@ using namespace arangodb;
using namespace arangodb::application_features; using namespace arangodb::application_features;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int { return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int {
ArangoGlobalContext context(argc, argv, BIN_DIRECTORY); ArangoGlobalContext context(argc, argv, BIN_DIRECTORY);
context.installHup(); context.installHup();

View File

@ -364,7 +364,7 @@ void ConsoleFeature::print(std::string const& message) {
void ConsoleFeature::openLog() { void ConsoleFeature::openLog() {
if (!_auditFile.empty()) { if (!_auditFile.empty()) {
_toAuditFile = fopen(_auditFile.c_str(), "w"); _toAuditFile = TRI_FOPEN(_auditFile.c_str(), "w");
std::ostringstream s; std::ostringstream s;

View File

@ -49,6 +49,7 @@ using namespace arangodb;
using namespace arangodb::application_features; using namespace arangodb::application_features;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int { return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int {
ArangoGlobalContext context(argc, argv, BIN_DIRECTORY); ArangoGlobalContext context(argc, argv, BIN_DIRECTORY);
context.installHup(); context.installHup();

View File

@ -41,6 +41,7 @@ using namespace arangodb;
using namespace arangodb::application_features; using namespace arangodb::application_features;
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int { return ClientFeature::runMain(argc, argv, [&](int argc, char* argv[]) -> int {
ArangoGlobalContext context(argc, argv, BIN_DIRECTORY); ArangoGlobalContext context(argc, argv, BIN_DIRECTORY);
context.installHup(); context.installHup();

View File

@ -22,12 +22,11 @@
#include "DaemonFeature.h" #include "DaemonFeature.h"
#include <fstream>
#include <iostream>
#include <thread> #include <thread>
#include <chrono> #include <chrono>
#include "Basics/FileUtils.h" #include "Basics/FileUtils.h"
#include "Basics/StringUtils.h"
#include "Logger/LogAppender.h" #include "Logger/LogAppender.h"
#include "Logger/Logger.h" #include "Logger/Logger.h"
#include "Logger/LoggerFeature.h" #include "Logger/LoggerFeature.h"
@ -147,15 +146,30 @@ void DaemonFeature::checkPidFile() {
} else if (FileUtils::exists(_pidFile) && FileUtils::size(_pidFile) > 0) { } else if (FileUtils::exists(_pidFile) && FileUtils::size(_pidFile) > 0) {
LOG_TOPIC(INFO, Logger::STARTUP) << "pid-file '" << _pidFile LOG_TOPIC(INFO, Logger::STARTUP) << "pid-file '" << _pidFile
<< "' already exists, verifying pid"; << "' already exists, verifying pid";
std::string oldPidS;
try {
oldPidS = arangodb::basics::FileUtils::slurp(_pidFile);
}
catch (arangodb::basics::Exception const& ex) {
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "Couldn't read PID file '"
<< _pidFile << "' - "
<< ex.what();
FATAL_ERROR_EXIT();
}
std::ifstream f(_pidFile.c_str()); basics::StringUtils::trimInPlace(oldPidS);
// file can be opened if (!oldPidS.empty()) {
if (f) {
TRI_pid_t oldPid; TRI_pid_t oldPid;
f >> oldPid; try {
oldPid = std::stol(oldPidS);
}
catch (std::invalid_argument const& ex) {
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "pid-file '" << _pidFile
<< "' doesn't contain a number.";
FATAL_ERROR_EXIT();
}
if (oldPid == 0) { if (oldPid == 0) {
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "pid-file '" << _pidFile LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "pid-file '" << _pidFile
<< "' is unreadable"; << "' is unreadable";
@ -316,15 +330,14 @@ void DaemonFeature::remapStandardFileDescriptors() {
} }
void DaemonFeature::writePidFile(int pid) { void DaemonFeature::writePidFile(int pid) {
std::ofstream out(_pidFile.c_str(), std::ios::trunc); try {
arangodb::basics::FileUtils::spit(_pidFile, std::to_string(pid), true);
if (!out) { }
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "cannot write pid-file '" catch (arangodb::basics::Exception const& ex) {
<< _pidFile << "'"; LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "cannot write pid-file '"
FATAL_ERROR_EXIT(); << _pidFile << "' - "
<< ex.what();
} }
out << pid;
} }
int DaemonFeature::waitForChildProcess(int pid) { int DaemonFeature::waitForChildProcess(int pid) {

View File

@ -70,13 +70,8 @@ void* LanguageFeature::prepareIcu(std::string const& binaryPath,
std::string const& binaryExecutionPath, std::string const& binaryExecutionPath,
std::string& path, std::string& path,
std::string const& binaryName) { std::string const& binaryName) {
char const* icuDataEnv = getenv("ICU_DATA");
std::string fn("icudtl.dat"); std::string fn("icudtl.dat");
TRI_GETENV("ICU_DATA", path);
if (icuDataEnv != nullptr) {
path = FileUtils::buildFilename(icuDataEnv, fn);
}
if (path.empty() || !TRI_IsRegularFile(path.c_str())) { if (path.empty() || !TRI_IsRegularFile(path.c_str())) {
if (!path.empty()) { if (!path.empty()) {
LOG_TOPIC(WARN, arangodb::Logger::FIXME) LOG_TOPIC(WARN, arangodb::Logger::FIXME)
@ -118,7 +113,8 @@ void* LanguageFeature::prepareIcu(std::string const& binaryPath,
#ifndef _WIN32 #ifndef _WIN32
setenv("ICU_DATA", icu_path.c_str(), 1); setenv("ICU_DATA", icu_path.c_str(), 1);
#else #else
SetEnvironmentVariable("ICU_DATA", icu_path.c_str()); UnicodeString uicuEnv(icu_path.c_str(), (uint16_t) icu_path.length());
SetEnvironmentVariableW(L"ICU_DATA", uicuEnv.getTerminatedBuffer());
#endif #endif
} }
} }

View File

@ -30,6 +30,7 @@
#ifdef TRI_HAVE_DIRECT_H #ifdef TRI_HAVE_DIRECT_H
#include <direct.h> #include <direct.h>
#endif #endif
#include <unicode/unistr.h>
#include "Basics/Exceptions.h" #include "Basics/Exceptions.h"
#include "Basics/OpenFilesTracker.h" #include "Basics/OpenFilesTracker.h"
@ -38,15 +39,6 @@
#include "Basics/tri-strings.h" #include "Basics/tri-strings.h"
#include "Logger/Logger.h" #include "Logger/Logger.h"
#if defined(_WIN32) && defined(_MSC_VER)
#define TRI_DIR_FN(item) item.name
#else
#define TRI_DIR_FN(item) item->d_name
#endif
namespace arangodb { namespace arangodb {
namespace basics { namespace basics {
@ -244,21 +236,6 @@ bool remove(std::string const& fileName, int* errorNumber) {
return (result != 0) ? false : true; return (result != 0) ? false : true;
} }
bool rename(std::string const& oldName, std::string const& newName,
int* errorNumber) {
if (errorNumber != nullptr) {
*errorNumber = 0;
}
int result = std::rename(oldName.c_str(), newName.c_str());
if (errorNumber != nullptr) {
*errorNumber = errno;
}
return (result != 0) ? false : true;
}
bool createDirectory(std::string const& name, int* errorNumber) { bool createDirectory(std::string const& name, int* errorNumber) {
if (errorNumber != nullptr) { if (errorNumber != nullptr) {
*errorNumber = 0; *errorNumber = 0;
@ -299,17 +276,22 @@ bool copyRecursive(std::string const& source, std::string const& target,
bool copyDirectoryRecursive(std::string const& source, bool copyDirectoryRecursive(std::string const& source,
std::string const& target, std::string& error) { std::string const& target, std::string& error) {
char* fn = nullptr;
bool rc = true; bool rc = true;
auto isSubDirectory = [](std::string const& name) -> bool { auto isSubDirectory = [](std::string const& name) -> bool {
return isDirectory(name); return isDirectory(name);
}; };
#ifdef TRI_HAVE_WIN32_LIST_FILES #ifdef TRI_HAVE_WIN32_LIST_FILES
struct _finddata_t oneItem; struct _wfinddata_t oneItem;
intptr_t handle; intptr_t handle;
std::string rcs;
std::string filter = source + "\\*"; std::string filter = source + "\\*";
handle = _findfirst(filter.c_str(), &oneItem);
UnicodeString f(filter.c_str());
handle = _wfindfirst(f.getTerminatedBuffer(), &oneItem);
if (handle == -1) { if (handle == -1) {
error = "directory " + source + "not found"; error = "directory " + source + "not found";
@ -317,6 +299,11 @@ bool copyDirectoryRecursive(std::string const& source,
} }
do { do {
rcs.clear();
UnicodeString d((wchar_t*) oneItem.name,
static_cast<int32_t>(wcslen(oneItem.name)));
d.toUTF8String<std::string>(rcs);
fn = (char*) rcs.c_str();
#else #else
DIR* filedir = opendir(source.c_str()); DIR* filedir = opendir(source.c_str());
@ -334,16 +321,17 @@ bool copyDirectoryRecursive(std::string const& source,
// to be thread-safe in reality, and newer versions of POSIX may require its // to be thread-safe in reality, and newer versions of POSIX may require its
// thread-safety formally, and in addition obsolete readdir_r() altogether // thread-safety formally, and in addition obsolete readdir_r() altogether
while ((oneItem = (readdir(filedir))) != nullptr) { while ((oneItem = (readdir(filedir))) != nullptr) {
fn = oneItem->d_name;
#endif #endif
// Now iterate over the items. // Now iterate over the items.
// check its not the pointer to the upper directory: // check its not the pointer to the upper directory:
if (!strcmp(TRI_DIR_FN(oneItem), ".") || if (!strcmp(fn, ".") ||
!strcmp(TRI_DIR_FN(oneItem), "..")) { !strcmp(fn, "..")) {
continue; continue;
} }
std::string dst = target + TRI_DIR_SEPARATOR_STR + fn;
std::string dst = target + TRI_DIR_SEPARATOR_STR + TRI_DIR_FN(oneItem); std::string src = source + TRI_DIR_SEPARATOR_STR + fn;
std::string src = source + TRI_DIR_SEPARATOR_STR + TRI_DIR_FN(oneItem);
// Handle subdirectories: // Handle subdirectories:
if (isSubDirectory(src)) { if (isSubDirectory(src)) {
@ -370,7 +358,7 @@ bool copyDirectoryRecursive(std::string const& source,
} }
} }
#ifdef TRI_HAVE_WIN32_LIST_FILES #ifdef TRI_HAVE_WIN32_LIST_FILES
} while (_findnext(handle, &oneItem) != -1); } while (_wfindnext(handle, &oneItem) != -1);
_findclose(handle); _findclose(handle);
@ -386,12 +374,15 @@ std::vector<std::string> listFiles(std::string const& directory) {
std::vector<std::string> result; std::vector<std::string> result;
#ifdef TRI_HAVE_WIN32_LIST_FILES #ifdef TRI_HAVE_WIN32_LIST_FILES
char* fn = nullptr;
struct _finddata_t fd; struct _wfinddata_t oneItem;
intptr_t handle; intptr_t handle;
std::string rcs;
std::string filter = directory + "\\*"; std::string filter = directory + "\\*";
handle = _findfirst(filter.c_str(), &fd); UnicodeString f(filter.c_str());
handle = _wfindfirst(f.getTerminatedBuffer(), &oneItem);
if (handle == -1) { if (handle == -1) {
TRI_set_errno(TRI_ERROR_SYS_ERROR); TRI_set_errno(TRI_ERROR_SYS_ERROR);
@ -402,10 +393,18 @@ std::vector<std::string> listFiles(std::string const& directory) {
} }
do { do {
if (strcmp(fd.name, ".") != 0 && strcmp(fd.name, "..") != 0) { rcs.clear();
result.push_back(fd.name); UnicodeString d((wchar_t*) oneItem.name,
static_cast<int32_t>(wcslen(oneItem.name)));
d.toUTF8String<std::string>(rcs);
fn = (char*) rcs.c_str();
if (!strcmp(fn, ".") ||
!strcmp(fn, "..")) {
continue;
} }
} while (_findnext(handle, &fd) != -1);
} while (_wfindnext(handle, &oneItem) != -1);
_findclose(handle); _findclose(handle);
@ -578,7 +577,8 @@ static void throwProgramError(std::string const& filename) {
std::string slurpProgram(std::string const& program) { std::string slurpProgram(std::string const& program) {
#ifdef _WIN32 #ifdef _WIN32
FILE* fp = _popen(program.c_str(), "r"); UnicodeString uprog(program.c_str(), (uint16_t) program.length());
FILE* fp = _wpopen(uprog.getTerminatedBuffer(), L"r");
#else #else
FILE* fp = popen(program.c_str(), "r"); FILE* fp = popen(program.c_str(), "r");
#endif #endif

View File

@ -72,10 +72,6 @@ void spit(std::string const& filename, StringBuffer const& content,
// returns true if a file could be removed // returns true if a file could be removed
bool remove(std::string const& fileName, int* errorNumber = nullptr); bool remove(std::string const& fileName, int* errorNumber = nullptr);
// returns true if a file could be renamed
bool rename(std::string const& oldName, std::string const& newName,
int* errorNumber = nullptr);
// creates a new directory // creates a new directory
bool createDirectory(std::string const& name, int* errorNumber = nullptr); bool createDirectory(std::string const& name, int* errorNumber = nullptr);
bool createDirectory(std::string const& name, int mask, int* errorNumber = nullptr); bool createDirectory(std::string const& name, int mask, int* errorNumber = nullptr);

View File

@ -28,6 +28,7 @@
#include <Shlwapi.h> #include <Shlwapi.h>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <unicode/locid.h>
#endif #endif
#include <algorithm> #include <algorithm>
@ -164,14 +165,10 @@ static void ListTreeRecursively(char const* full, char const* path,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static std::string LocateConfigDirectoryEnv() { static std::string LocateConfigDirectoryEnv() {
char const* v = getenv("ARANGODB_CONFIG_PATH"); std::string r;
if (!TRI_GETENV("ARANGODB_CONFIG_PATH", r)) {
if (v == nullptr) {
return std::string(); return std::string();
} }
std::string r(v);
NormalizePath(r); NormalizePath(r);
while (!r.empty() && IsDirSeparatorChar(r[r.size() - 1])) { while (!r.empty() && IsDirSeparatorChar(r[r.size() - 1])) {
r.pop_back(); r.pop_back();
@ -328,7 +325,8 @@ bool TRI_ExistsFile(char const* path) {
int TRI_ChMod(char const* path, long mode, std::string& err) { int TRI_ChMod(char const* path, long mode, std::string& err) {
int res; int res;
#ifdef _WIN32 #ifdef _WIN32
res = _chmod(path, static_cast<int>(mode)); UnicodeString wpath(path);
res = _wchmod(wpath.getTerminatedBuffer(), static_cast<int>(mode));
#else #else
res = chmod(path, mode); res = chmod(path, mode);
#endif #endif
@ -655,18 +653,26 @@ std::vector<std::string> TRI_FilesDirectory(char const* path) {
std::string filter(path); std::string filter(path);
filter.append("\\*"); filter.append("\\*");
struct _finddata_t fd; struct _wfinddata_t fd;
intptr_t handle = _findfirst(filter.c_str(), &fd);
UnicodeString wfilter(filter.c_str());
intptr_t handle = _wfindfirst(wfilter.getTerminatedBuffer(), &fd);
if (handle == -1) { if (handle == -1) {
return result; return result;
} }
std::string ufn;
UnicodeString fn;
do { do {
if (strcmp(fd.name, ".") != 0 && strcmp(fd.name, "..") != 0) { if (wcscmp(fd.name, L".") != 0 && wcscmp(fd.name, L"..") != 0) {
result.emplace_back(fd.name); ufn.clear();
fn = fd.name;
fn.toUTF8String<std::string>(ufn);
result.emplace_back(ufn);
} }
} while (_findnext(handle, &fd) != -1); } while (_wfindnext(handle, &fd) != -1);
_findclose(handle); _findclose(handle);
@ -724,7 +730,11 @@ int TRI_RenameFile(char const* old, char const* filename, long* systemError,
TRI_ERRORBUF; TRI_ERRORBUF;
#ifdef _WIN32 #ifdef _WIN32
BOOL moveResult = 0; BOOL moveResult = 0;
moveResult = MoveFileExA(old, filename,
UnicodeString oldf(old);
UnicodeString newf(filename);
moveResult = MoveFileExW(oldf.getTerminatedBuffer(), newf.getTerminatedBuffer(),
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING); MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
if (!moveResult) { if (!moveResult) {
@ -957,7 +967,8 @@ int TRI_CreateLockFile(char const* filename) {
} }
} }
HANDLE fd = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, UnicodeString fn(filename);
HANDLE fd = CreateFileW(fn.getTerminatedBuffer(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL); FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE) { if (fd == INVALID_HANDLE_VALUE) {
@ -1467,13 +1478,13 @@ std::string TRI_BinaryName(char const* argv0) {
std::string TRI_LocateBinaryPath(char const* argv0) { std::string TRI_LocateBinaryPath(char const* argv0) {
#if _WIN32 #if _WIN32
char buff[4096]; wchar_t buff[4096];
int res = GetModuleFileName(NULL, buff, sizeof(buff)); int res = GetModuleFileNameW(NULL, buff, sizeof(buff));
if (res != 0) { if (res != 0) {
buff[4095] = '\0'; buff[4095] = '\0';
char* q = buff + res; wchar_t* q = buff + res;
while (buff < q) { while (buff < q) {
if (*q == '\\' || *q == '/') { if (*q == '\\' || *q == '/') {
@ -1484,7 +1495,13 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
--q; --q;
} }
return std::string(buff); size_t len = q - buff;
UnicodeString fn(buff, static_cast<int32_t>(len));
std::string ufn;
fn.toUTF8String<std::string>(ufn);
return ufn;
} }
return std::string(); return std::string();
@ -1506,10 +1523,9 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
// check PATH variable // check PATH variable
else { else {
p = getenv("PATH"); std::string pv;
if (TRI_GETENV("PATH", pv)) {
if (p != nullptr) { std::vector<std::string> files = basics::StringUtils::split(pv, ':', '\0');
std::vector<std::string> files = basics::StringUtils::split(std::string(p), ':', '\0');
for (auto const& prefix : files) { for (auto const& prefix : files) {
std::string full; std::string full;
@ -1659,7 +1675,11 @@ bool TRI_CopyFile(std::string const& src, std::string const& dst,
std::string& error) { std::string& error) {
#ifdef _WIN32 #ifdef _WIN32
TRI_ERRORBUF; TRI_ERRORBUF;
bool rc = CopyFile(src.c_str(), dst.c_str(), true) != 0;
UnicodeString s(src.c_str());
UnicodeString d(dst.c_str());
bool rc = CopyFileW(s.getTerminatedBuffer(), d.getTerminatedBuffer(), true) != 0;
if (!rc) { if (!rc) {
TRI_SYSTEM_ERROR(); TRI_SYSTEM_ERROR();
error = "failed to copy " + src + " to " + dst + ": " + TRI_GET_ERRORBUF; error = "failed to copy " + src + " to " + dst + ": " + TRI_GET_ERRORBUF;
@ -1789,14 +1809,15 @@ bool TRI_CopySymlink(std::string const& srcItem, std::string const& dstItem,
#ifdef _WIN32 #ifdef _WIN32
std::string TRI_HomeDirectory() { std::string TRI_HomeDirectory() {
char const* drive = getenv("HOMEDRIVE"); std::string drive;
char const* path = getenv("HOMEPATH"); std::string path;
if (drive == nullptr || path == nullptr) { if (! TRI_GETENV("HOMEDRIVE", drive) ||
! TRI_GETENV("HOMEPATH", path)) {
return std::string(); return std::string();
} }
return std::string(drive) + std::string(path); return drive + path;
} }
#else #else
@ -1833,7 +1854,7 @@ int TRI_Crc32File(char const* path, uint32_t* crc) {
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
} }
fin = fopen(path, "rb"); fin = TRI_FOPEN(path, "rb");
if (fin == nullptr) { if (fin == nullptr) {
TRI_Free(buffer); TRI_Free(buffer);
@ -1901,7 +1922,7 @@ static std::string getTempPath() {
// .......................................................................... // ..........................................................................
#define LOCAL_MAX_PATH_BUFFER 2049 #define LOCAL_MAX_PATH_BUFFER 2049
TCHAR tempPathName[LOCAL_MAX_PATH_BUFFER]; wchar_t tempPathName[LOCAL_MAX_PATH_BUFFER];
DWORD dwReturnValue = 0; DWORD dwReturnValue = 0;
// .......................................................................... // ..........................................................................
// Attempt to locate the path where the users temporary files are stored // Attempt to locate the path where the users temporary files are stored
@ -1918,15 +1939,17 @@ static std::string getTempPath() {
The path specified by the USERPROFILE environment variable. The path specified by the USERPROFILE environment variable.
The Windows directory. The Windows directory.
*/ */
dwReturnValue = GetTempPath(LOCAL_MAX_PATH_BUFFER, tempPathName); dwReturnValue = GetTempPathW(LOCAL_MAX_PATH_BUFFER, tempPathName);
if ((dwReturnValue > LOCAL_MAX_PATH_BUFFER) || (dwReturnValue == 0)) { if ((dwReturnValue > LOCAL_MAX_PATH_BUFFER) || (dwReturnValue == 0)) {
// something wrong // something wrong
LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "GetTempPathA failed: LOCAL_MAX_PATH_BUFFER=" LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "GetTempPathW failed: LOCAL_MAX_PATH_BUFFER="
<< LOCAL_MAX_PATH_BUFFER << ":dwReturnValue=" << dwReturnValue; << LOCAL_MAX_PATH_BUFFER << ":dwReturnValue=" << dwReturnValue;
} }
std::string result(tempPathName); UnicodeString tmpPathW(tempPathName, dwReturnValue);
std::string result;
tmpPathW.toUTF8String<std::string>(result);
// ........................................................................... // ...........................................................................
// Whether or not UNICODE is defined, we assume that the temporary file name // Whether or not UNICODE is defined, we assume that the temporary file name
// fits in the ascii set of characters. This is a small compromise so that // fits in the ascii set of characters. This is a small compromise so that
@ -1947,8 +1970,14 @@ static std::string getTempPath() {
} }
static int mkDTemp(char* s, size_t bufferSize) { static int mkDTemp(char* s, size_t bufferSize) {
auto rc = _mktemp_s(s, bufferSize); std::string out;
UnicodeString sw(s);
// this will overwrite the _XXX part of the string:
auto rc = _wmktemp_s((wchar_t*)sw.getTerminatedBuffer(), bufferSize);
if (rc == 0) { if (rc == 0) {
// if it worked out, we need to return the utf8 version:
sw.toUTF8String<std::string>(out);
memcpy(s, out.c_str(), bufferSize);
rc = TRI_MKDIR(s, 0700); rc = TRI_MKDIR(s, 0700);
} }
return rc; return rc;
@ -2118,7 +2147,7 @@ int TRI_GetTempName(char const* directory, std::string& result, bool createFile,
errorMessage = std::string("Tempfile already exists! ") + filename; errorMessage = std::string("Tempfile already exists! ") + filename;
} else { } else {
if (createFile) { if (createFile) {
FILE* fd = fopen(filename.c_str(), "wb"); FILE* fd = TRI_FOPEN(filename.c_str(), "wb");
if (fd != nullptr) { if (fd != nullptr) {
fclose(fd); fclose(fd);
@ -2313,7 +2342,8 @@ int TRI_CreateDatafile(std::string const& filename, size_t maximalSize) {
bool TRI_PathIsAbsolute(std::string const& path) { bool TRI_PathIsAbsolute(std::string const& path) {
#if _WIN32 #if _WIN32
return !PathIsRelative(path.c_str()); UnicodeString upath(path.c_str(), (uint16_t) path.length());
return !PathIsRelativeW(upath.getTerminatedBuffer());
#else #else
return (!path.empty()) && path.c_str()[0] == '/'; return (!path.empty()) && path.c_str()[0] == '/';
#endif #endif
@ -2334,3 +2364,27 @@ void TRI_InitializeFiles() {
void TRI_ShutdownFiles() {} void TRI_ShutdownFiles() {}
bool TRI_GETENV(char const* which, std::string &value) {
#ifdef _WIN32
UnicodeString uwhich(which);
wchar_t const *v = _wgetenv(uwhich.getTerminatedBuffer());
if (v == nullptr) {
return false;
}
value.clear();
UnicodeString vu(v);
vu.toUTF8String<std::string>(value);
return true;
#else
char const* v = getenv(which);
if (v == nullptr) {
return false;
}
value.clear();
value = v;
return true;
#endif
}

View File

@ -364,4 +364,9 @@ void TRI_InitializeFiles();
void TRI_ShutdownFiles(); void TRI_ShutdownFiles();
////////////////////////////////////////////////////////////////////////////////
/// @brief if which is found, value is overwriten, true returned.
////////////////////////////////////////////////////////////////////////////////
bool TRI_GETENV(char const* which, std::string &value);
#endif #endif

View File

@ -172,6 +172,7 @@
#define TRI_LSEEK ::lseek #define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b)) #define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b)) #define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read #define TRI_READ ::read
#define TRI_RMDIR ::rmdir #define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat #define TRI_STAT ::stat
@ -192,6 +193,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno) #define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \ #define TRI_SYSTEM_ERROR() \
{} {}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets // sockets
@ -329,6 +331,7 @@
#define TRI_LSEEK ::lseek #define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b)) #define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b)) #define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read #define TRI_READ ::read
#define TRI_RMDIR ::rmdir #define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat #define TRI_STAT ::stat
@ -349,6 +352,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno) #define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \ #define TRI_SYSTEM_ERROR() \
{} {}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets // sockets
@ -473,6 +477,7 @@
#define TRI_LSEEK ::lseek #define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b)) #define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b)) #define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read #define TRI_READ ::read
#define TRI_RMDIR ::rmdir #define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat #define TRI_STAT ::stat
@ -493,6 +498,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno) #define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \ #define TRI_SYSTEM_ERROR() \
{} {}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets // sockets
@ -631,6 +637,7 @@
#define TRI_LSEEK ::lseek #define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b)) #define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b)) #define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read #define TRI_READ ::read
#define TRI_RMDIR ::rmdir #define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat #define TRI_STAT ::stat
@ -651,6 +658,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno) #define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \ #define TRI_SYSTEM_ERROR() \
{} {}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets // sockets
@ -704,7 +712,6 @@
#include <WinSock2.h> #include <WinSock2.h>
#include <io.h> #include <io.h>
#include <stdio.h> #include <stdio.h>
// available include files // available include files
#define TRI_HAVE_DIRECT_H 1 #define TRI_HAVE_DIRECT_H 1
@ -829,18 +836,13 @@ typedef unsigned char bool;
#define O_RDONLY _O_RDONLY #define O_RDONLY _O_RDONLY
#define TRI_CHDIR ::_chdir
#define TRI_CLOSE ::_close #define TRI_CLOSE ::_close
#define TRI_CREATE(a, b, c) TRI_createFile((a), (b), (c)) #define TRI_CREATE(a, b, c) TRI_createFile((a), (b), (c))
#define TRI_FSTAT ::_fstat64 #define TRI_FSTAT ::_fstat64
#define TRI_GETCWD ::_getcwd
#define TRI_LSEEK ::_lseeki64 #define TRI_LSEEK ::_lseeki64
#define TRI_MKDIR(a, b) ::_mkdir((a)) #define TRI_MKDIR(a, b) TRI_MKDIR_WIN32(a)
#define TRI_OPEN(a, b) TRI_OPEN_WIN32((a), (b)) #define TRI_OPEN(a, b) TRI_OPEN_WIN32((a), (b))
#define TRI_READ ::_read #define TRI_READ ::_read
#define TRI_RMDIR ::_rmdir
#define TRI_STAT ::_stat64
#define TRI_UNLINK ::_unlink
#define TRI_WRITE ::_write #define TRI_WRITE ::_write
#define TRI_FDOPEN(a, b) ::_fdopen((a), (b)) #define TRI_FDOPEN(a, b) ::_fdopen((a), (b))
@ -853,6 +855,17 @@ typedef unsigned char bool;
#define TRI_ERRORBUF char windowsErrorBuf[256] = ""; #define TRI_ERRORBUF char windowsErrorBuf[256] = "";
#define TRI_GET_ERRORBUF windowsErrorBuf #define TRI_GET_ERRORBUF windowsErrorBuf
#define TRI_GET_ARGV(ARGC, ARGV) TRI_GET_ARGV_WIN(ARGC, ARGV)
// Implemented wrappers in win-utils.cpp:
FILE* TRI_FOPEN(char const* filename, char const* mode);
int TRI_CHDIR(char const* dirname);
int TRI_STAT(char const* path, TRI_stat_t* buffer);
char* TRI_GETCWD(char* buffer, int maxlen);
int TRI_MKDIR_WIN32(char const* dirname);
int TRI_RMDIR(char const* dirname);
int TRI_UNLINK(char const* filename);
void TRI_GET_ARGV_WIN(int& argc, char** argv);
// system error string macro requires ERRORBUF to instantiate its buffer before. // system error string macro requires ERRORBUF to instantiate its buffer before.

View File

@ -44,6 +44,7 @@
#ifdef _WIN32 #ifdef _WIN32
#include <Psapi.h> #include <Psapi.h>
#include <TlHelp32.h> #include <TlHelp32.h>
#include <unicode/unistr.h>
#endif #endif
#include "Logger/Logger.h" #include "Logger/Logger.h"
@ -326,20 +327,57 @@ static int appendQuotedArg(TRI_string_buffer_t* buf, char const* p) {
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
static char* makeWindowsArgs(ExternalProcess* external) {
TRI_string_buffer_t* buf; static int wAppendQuotedArg(std::wstring &buf, wchar_t const* p) {
buf += L'"';
while (*p != 0) {
unsigned int i;
unsigned int NumberBackslashes = 0;
wchar_t const* q = p;
while (*q == L'\\') {
++q;
++NumberBackslashes;
}
if (*q == 0) {
// Escape all backslashes, but let the terminating
// double quotation mark we add below be interpreted
// as a metacharacter.
for (i = 0; i < NumberBackslashes; i++) {
buf += L'\\';
buf += L'\\';
}
break;
} else if (*q == L'"') {
// Escape all backslashes and the following
// double quotation mark.
for (i = 0; i < NumberBackslashes; i++) {
buf += L'\\';
buf += L'\\';
}
buf += L'\\';
buf += *q;
} else {
// Backslashes aren't special here.
for (i = 0; i < NumberBackslashes; i++) {
buf += L'\\';
}
buf += *q;
}
p = ++q;
}
buf += L'"';
return TRI_ERROR_NO_ERROR;
}
static std::wstring makeWindowsArgs(ExternalProcess* external) {
size_t i; size_t i;
int err = TRI_ERROR_NO_ERROR; int err = TRI_ERROR_NO_ERROR;
char* res; std::wstring res;
buf = TRI_CreateStringBuffer();
if (buf == nullptr) {
return nullptr;
}
if (( external->_executable.find('/') == std::string::npos) && if (( external->_executable.find('/') == std::string::npos) &&
( external->_executable.find('\\') == std::string::npos)) { ( external->_executable.find('\\') == std::string::npos)) {
// oK, this is a binary without path, start the lookup. // oK, this is a binary without path, start the lookup.
// This will most probably break with non-ascii paths.
char buf[MAX_PATH]; char buf[MAX_PATH];
char *pBuf; char *pBuf;
DWORD n; DWORD n;
@ -349,34 +387,32 @@ static char* makeWindowsArgs(ExternalProcess* external) {
} }
} }
TRI_ReserveStringBuffer(buf, 1024); UnicodeString uwargs(external->_executable.c_str());
err = appendQuotedArg(buf, external->_executable.c_str());
err = wAppendQuotedArg(res, uwargs.getTerminatedBuffer());
if (err != TRI_ERROR_NO_ERROR) { if (err != TRI_ERROR_NO_ERROR) {
TRI_FreeStringBuffer(buf);
return nullptr; return nullptr;
} }
for (i = 1; i < external->_numberArguments; i++) { for (i = 1; i < external->_numberArguments; i++) {
err = TRI_AppendCharStringBuffer(buf, ' '); res += L' ';
uwargs = external->_arguments[i];
err = wAppendQuotedArg(res, uwargs.getTerminatedBuffer());
if (err != TRI_ERROR_NO_ERROR) { if (err != TRI_ERROR_NO_ERROR) {
TRI_FreeStringBuffer(buf);
return nullptr; return nullptr;
} }
err = appendQuotedArg(buf, external->_arguments[i]);
} }
res = TRI_StealStringBuffer(buf);
TRI_FreeStringBuffer(buf);
return res; return res;
} }
static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) { static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
char* args; std::wstring args;
PROCESS_INFORMATION piProcInfo; PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo; STARTUPINFOW siStartInfo;
BOOL bFuncRetn = FALSE; BOOL bFuncRetn = FALSE;
TRI_ERRORBUF; TRI_ERRORBUF;
args = makeWindowsArgs(external); args = makeWindowsArgs(external);
if (args == nullptr) { if (args.length() == 0) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "execute of '" << external->_executable LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "execute of '" << external->_executable
<< "' failed making args"; << "' failed making args";
return false; return false;
@ -386,8 +422,8 @@ static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
// set up members of the STARTUPINFO structure // set up members of the STARTUPINFO structure
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); ZeroMemory(&siStartInfo, sizeof(STARTUPINFOW));
siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.cb = sizeof(STARTUPINFOW);
siStartInfo.dwFlags = STARTF_USESTDHANDLES; siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = rd ? rd : nullptr; siStartInfo.hStdInput = rd ? rd : nullptr;
@ -395,8 +431,8 @@ static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
// create the child process // create the child process
bFuncRetn = CreateProcess(NULL, bFuncRetn = CreateProcessW(NULL,
args, // command line (LPWSTR)args.c_str(), // command line
NULL, // process security attributes NULL, // process security attributes
NULL, // primary thread security attributes NULL, // primary thread security attributes
TRUE, // handles are inherited TRUE, // handles are inherited
@ -406,8 +442,6 @@ static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
&siStartInfo, // STARTUPINFO pointer &siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION &piProcInfo); // receives PROCESS_INFORMATION
TRI_Free(args);
if (bFuncRetn == FALSE) { if (bFuncRetn == FALSE) {
TRI_SYSTEM_ERROR(); TRI_SYSTEM_ERROR();
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "execute of '" << external->_executable LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "execute of '" << external->_executable

View File

@ -26,6 +26,7 @@
#include "Basics/files.h" #include "Basics/files.h"
#include "Basics/FileUtils.h" #include "Basics/FileUtils.h"
#include "Basics/tri-strings.h" #include "Basics/tri-strings.h"
#include "Basics/Common.h"
#include "Zip/unzip.h" #include "Zip/unzip.h"
#include "Zip/zip.h" #include "Zip/zip.h"
@ -147,7 +148,7 @@ static int ExtractCurrentFile(unzFile uf, void* buffer, size_t const bufferSize,
} }
// try to write the outfile // try to write the outfile
fout = fopen(fullPath.c_str(), "wb"); fout = TRI_FOPEN(fullPath.c_str(), "wb");
// cannot write to outfile. this may be due to the target directory missing // cannot write to outfile. this may be due to the target directory missing
if (fout == nullptr && !skipPaths && if (fout == nullptr && !skipPaths &&
@ -166,7 +167,7 @@ static int ExtractCurrentFile(unzFile uf, void* buffer, size_t const bufferSize,
*(filenameWithoutPath - 1) = c; *(filenameWithoutPath - 1) = c;
// try again // try again
fout = fopen(fullPath.c_str(), "wb"); fout = TRI_FOPEN(fullPath.c_str(), "wb");
} else if (fout == nullptr) { } else if (fout == nullptr) {
// try to create the target directory recursively // try to create the target directory recursively
// strip filename so we only have the directory name // strip filename so we only have the directory name
@ -178,7 +179,7 @@ static int ExtractCurrentFile(unzFile uf, void* buffer, size_t const bufferSize,
} }
// try again // try again
fout = fopen(fullPath.c_str(), "wb"); fout = TRI_FOPEN(fullPath.c_str(), "wb");
} }
if (fout == nullptr) { if (fout == nullptr) {
@ -340,7 +341,7 @@ int TRI_ZipFile(char const* filename, char const* dir,
break; break;
} }
FILE* fin = fopen(fullfile.c_str(), "rb"); FILE* fin = TRI_FOPEN(fullfile.c_str(), "rb");
if (fin == nullptr) { if (fin == nullptr) {
break; break;
@ -394,7 +395,7 @@ int TRI_Adler32(char const* filename, uint32_t& checksum) {
} }
TRI_DEFER(TRI_CLOSE(fd)); TRI_DEFER(TRI_CLOSE(fd));
struct TRI_STAT statbuf; TRI_stat_t statbuf;
int res = TRI_FSTAT(fd, &statbuf); int res = TRI_FSTAT(fd, &statbuf);
if (res < 0) { if (res < 0) {
TRI_ERRORBUF; TRI_ERRORBUF;

View File

@ -24,6 +24,15 @@
#include <errno.h> #include <errno.h>
#include <io.h> #include <io.h>
#include <locale>
#include <iomanip>
#include <codecvt>
#include <sys/stat.h>
#include <wchar.h>
#include <unicode/locid.h>
#include <unicode/uchar.h>
#include <unicode/unistr.h>
#include <sys/types.h>
#include "win-utils.h" #include "win-utils.h"
@ -33,14 +42,13 @@
#include <crtdbg.h> #include <crtdbg.h>
#include <atlstr.h> #include <atlstr.h>
#include <VersionHelpers.h> #include <VersionHelpers.h>
#include <unicode/uchar.h>
#include <unicode/unistr.h>
#include "Logger/Logger.h" #include "Logger/Logger.h"
#include "Basics/files.h" #include "Basics/files.h"
#include "Basics/StringUtils.h" #include "Basics/StringUtils.h"
#include "Basics/tri-strings.h" #include "Basics/tri-strings.h"
#include "Basics/directories.h" #include "Basics/directories.h"
#include "Basics/Common.h"
using namespace arangodb::basics; using namespace arangodb::basics;
@ -181,11 +189,16 @@ int initializeWindows(const TRI_win_initialize_e initializeWhat,
int TRI_createFile(char const* filename, int openFlags, int modeFlags) { int TRI_createFile(char const* filename, int openFlags, int modeFlags) {
HANDLE fileHandle; HANDLE fileHandle;
int fileDescriptor; int fileDescriptor;
UnicodeString fn(filename);
fileHandle = fileHandle =
CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, CreateFileW(fn.getTerminatedBuffer(),
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, GENERIC_READ | GENERIC_WRITE,
(openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW, 0, NULL); FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
(openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW,
0,
NULL);
if (fileHandle == INVALID_HANDLE_VALUE) { if (fileHandle == INVALID_HANDLE_VALUE) {
return -1; return -1;
@ -228,8 +241,12 @@ int TRI_OPEN_WIN32(char const* filename, int openFlags) {
break; break;
} }
fileHandle = CreateFileA( UnicodeString fn(filename);
filename, mode, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, fileHandle = CreateFileW(fn.getTerminatedBuffer(),
mode,
FILE_SHARE_DELETE |
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL); NULL, OPEN_EXISTING, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) { if (fileHandle == INVALID_HANDLE_VALUE) {
@ -241,6 +258,64 @@ int TRI_OPEN_WIN32(char const* filename, int openFlags) {
return fileDescriptor; return fileDescriptor;
} }
FILE* TRI_FOPEN(char const* filename, char const* mode) {
UnicodeString fn(filename);
UnicodeString umod(mode);
return _wfopen(fn.getTerminatedBuffer(), umod.getTerminatedBuffer());
}
int TRI_CHDIR(char const* dirname) {
UnicodeString dn(dirname);
return ::_wchdir(dn.getTerminatedBuffer());
}
int TRI_STAT(char const* path, TRI_stat_t* buffer) {
UnicodeString p(path);
auto rc = ::_wstat64(p.getTerminatedBuffer(), buffer);
return rc;
}
char *TRI_GETCWD(char* buffer, int maxlen){
char* rc = nullptr;
wchar_t* rcw;
int wBufLen = maxlen;
wchar_t* wbuf = (wchar_t*)malloc(wBufLen * sizeof(wchar_t));
if (wbuf == nullptr) {
return nullptr;
}
rcw = ::_wgetcwd(wbuf, wBufLen);
if (rcw != nullptr) {
std::string rcs;
UnicodeString d(wbuf, static_cast<int32_t>(wcslen(wbuf)));
d.toUTF8String<std::string>(rcs);
if (rcs.length() + 1 < maxlen) {
memcpy(buffer, rcs.c_str(), rcs.length() + 1);
rc = buffer;
}
}
free(wbuf);
return rc;
}
int TRI_MKDIR_WIN32(char const* dirname) {
UnicodeString dir(dirname);
return ::_wmkdir(dir.getTerminatedBuffer());
}
int TRI_RMDIR(char const* dirname) {
UnicodeString dir(dirname);
return ::_wrmdir(dir.getTerminatedBuffer());
}
int TRI_UNLINK(char const* filename) {
UnicodeString fn(filename);
return ::_wunlink(fn.getTerminatedBuffer());
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief converts a Windows error to a *nix system error /// @brief converts a Windows error to a *nix system error
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -411,7 +486,7 @@ int TRI_MapSystemError(DWORD error) {
static HANDLE hEventLog = INVALID_HANDLE_VALUE; static HANDLE hEventLog = INVALID_HANDLE_VALUE;
bool TRI_InitWindowsEventLog(void) { bool TRI_InitWindowsEventLog(void) {
hEventLog = RegisterEventSource(NULL, "ArangoDB"); hEventLog = RegisterEventSourceW(NULL, L"ArangoDB");
if (NULL == hEventLog) { if (NULL == hEventLog) {
// well, fail then. // well, fail then.
return false; return false;
@ -424,13 +499,6 @@ void TRI_CloseWindowsEventlog(void) {
hEventLog = INVALID_HANDLE_VALUE; hEventLog = INVALID_HANDLE_VALUE;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief logs a message to the windows event log.
/// we rather are keen on logging something at all then on being able to work
/// with fancy dynamic buffers; thus we work with a static buffer.
/// the arango internal logging will handle that usually.
////////////////////////////////////////////////////////////////////////////////
// No clue why there is no header for these... // No clue why there is no header for these...
#define MSG_INVALID_COMMAND ((DWORD)0xC0020100L) #define MSG_INVALID_COMMAND ((DWORD)0xC0020100L)
#define UI_CATEGORY ((WORD)0x00000003L) #define UI_CATEGORY ((WORD)0x00000003L)
@ -447,10 +515,27 @@ void TRI_LogWindowsEventlog(char const* func, char const* file, int line,
DWORD len = _snprintf(buf, sizeof(buf) - 1, "%s", message.c_str()); DWORD len = _snprintf(buf, sizeof(buf) - 1, "%s", message.c_str());
buf[sizeof(buf) - 1] = '\0'; buf[sizeof(buf) - 1] = '\0';
UnicodeString ubufs[]{
UnicodeString(buf, len),
UnicodeString(file),
UnicodeString(func),
UnicodeString(linebuf)
};
LPCWSTR buffers[] = {
ubufs[0].getTerminatedBuffer(),
ubufs[1].getTerminatedBuffer(),
ubufs[2].getTerminatedBuffer(),
ubufs[3].getTerminatedBuffer(),
nullptr
};
// Try to get messages through to windows syslog... // Try to get messages through to windows syslog...
if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY, if (!ReportEventW(hEventLog,
MSG_INVALID_COMMAND, NULL, 4, 0, (LPCSTR*)logBuffers, EVENTLOG_ERROR_TYPE,
NULL)) { UI_CATEGORY,
MSG_INVALID_COMMAND,
NULL,
4, 0,
buffers, NULL)) {
// well, fail then... // well, fail then...
} }
} }
@ -468,10 +553,27 @@ void TRI_LogWindowsEventlog(char const* func, char const* file, int line,
DWORD len = _vsnprintf(buf, sizeof(buf) - 1, fmt, ap); DWORD len = _vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
buf[sizeof(buf) - 1] = '\0'; buf[sizeof(buf) - 1] = '\0';
UnicodeString ubufs[]{
UnicodeString(buf, len),
UnicodeString(file),
UnicodeString(func),
UnicodeString(linebuf)
};
LPCWSTR buffers[] = {
ubufs[0].getTerminatedBuffer(),
ubufs[1].getTerminatedBuffer(),
ubufs[2].getTerminatedBuffer(),
ubufs[3].getTerminatedBuffer(),
nullptr
};
// Try to get messages through to windows syslog... // Try to get messages through to windows syslog...
if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY, if (!ReportEventW(hEventLog,
MSG_INVALID_COMMAND, NULL, 4, 0, (LPCSTR*)logBuffers, EVENTLOG_ERROR_TYPE,
NULL)) { UI_CATEGORY,
MSG_INVALID_COMMAND,
NULL,
4, 0,
buffers, NULL)) {
// well, fail then... // well, fail then...
} }
} }
@ -656,3 +758,29 @@ std::string getFileNameFromHandle(HANDLE fileHandle) {
} }
return std::string((LPCTSTR)CString(FileInformation->FileName)); return std::string((LPCTSTR)CString(FileInformation->FileName));
} }
static std::vector<std::string> argVec;
void TRI_GET_ARGV_WIN(int& argc, char** argv) {
auto wargStr = GetCommandLineW();
// if you want your argc in unicode, all you gonna do
// is ask:
auto wargv = CommandLineToArgvW(wargStr, &argc);
argVec.reserve(argc);
UnicodeString buf;
std::string uBuf;
for (int i = 0; i < argc; i++) {
uBuf.clear();
// convert one UTF16 argument to utf8:
buf = wargv[i];
buf.toUTF8String<std::string>(uBuf);
// memorize the utf8 value to keep the instance:
argVec.push_back(uBuf);
// Now overwrite our original argc entry with the utf8 one:
argv[i] = (char*) argVec[i].c_str();
}
}

View File

@ -202,7 +202,7 @@ void LogAppenderFile::reopenAll() {
backup.append(".old"); backup.append(".old");
FileUtils::remove(backup); FileUtils::remove(backup);
FileUtils::rename(filename, backup); TRI_RenameFile(filename.c_str(), backup.c_str());
// open new log file // open new log file
int fd = TRI_TRACKED_CREATE_FILE(filename.c_str(), int fd = TRI_TRACKED_CREATE_FILE(filename.c_str(),
@ -210,7 +210,7 @@ void LogAppenderFile::reopenAll() {
S_IRUSR | S_IWUSR | S_IRGRP); S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) { if (fd < 0) {
FileUtils::rename(backup, filename); TRI_RenameFile(backup.c_str(), filename.c_str());
continue; continue;
} }

View File

@ -25,10 +25,11 @@
#include "Basics/FileUtils.h" #include "Basics/FileUtils.h"
#include <fstream>
#include <regex> #include <regex>
#include <sstream>
#include "ProgramOptions/ProgramOptions.h" #include "ProgramOptions/ProgramOptions.h"
#include <unicode/unistr.h>
namespace arangodb { namespace arangodb {
namespace options { namespace options {
@ -67,25 +68,25 @@ class IniFileParser {
return _options->fail( return _options->fail(
"unable to open configuration file: no configuration file specified"); "unable to open configuration file: no configuration file specified");
} }
std::string buf;
std::ifstream ifs(filename, std::ifstream::in); try {
buf = arangodb::basics::FileUtils::slurp(filename);
if (!ifs.is_open()) { }
return _options->fail("unable to open configuration file '" + filename + catch (arangodb::basics::Exception const& ex) {
"'"); return _options->fail(std::string("Couldn't open configuration file: '") +
filename + "' - " + ex.what());
return true;
} }
bool isCommunity = false; bool isCommunity = false;
bool isEnterprise = false; bool isEnterprise = false;
std::string currentSection; std::string currentSection;
size_t lineNumber = 0; size_t lineNumber = 0;
while (ifs.good()) { std::istringstream iss(buf);
std::string line; for (std::string line; std::getline(iss, line); ) {
basics::StringUtils::trimInPlace(line);
++lineNumber; ++lineNumber;
std::getline(ifs, line);
if (std::regex_match(line, _matchers.comment)) { if (std::regex_match(line, _matchers.comment)) {
// skip over comments // skip over comments
continue; continue;

View File

@ -76,24 +76,21 @@ std::string arangodb::options::EnvironmentTranslator(std::string const& value,
if (q < e) { if (q < e) {
std::string k = std::string(t, q); std::string k = std::string(t, q);
char const* v = getenv(k.c_str());
std::string vv; std::string vv;
if (!TRI_GETENV(k.c_str(), vv) || (vv.length() == 0)) {
if (v != nullptr && *v == '\0') {
v = nullptr;
}
if (v == nullptr) {
auto iter = environment.find(k); auto iter = environment.find(k);
if (iter != environment.end()) { if (iter != environment.end()) {
v = iter->second.c_str(); vv = iter->second;
} }
} }
if (v == nullptr) { if (vv.length() == 0) {
if (k == "PID") {
vv = std::to_string(Thread::currentProcessId());
}
#if _WIN32 #if _WIN32
if (TRI_EqualString(k.c_str(), "ROOTDIR")) { else if (k == "ROOTDIR") {
vv = TRI_LocateInstallDirectory(nullptr, binaryPath); vv = TRI_LocateInstallDirectory(nullptr, binaryPath);
if (!vv.empty()) { if (!vv.empty()) {
@ -103,13 +100,8 @@ std::string arangodb::options::EnvironmentTranslator(std::string const& value,
vv.pop_back(); vv.pop_back();
} }
} }
} else
#endif
if (TRI_EqualString(k.c_str(), "PID")) {
vv = std::to_string(Thread::currentProcessId());
} }
} else { #endif
vv = v;
} }
result += vv; result += vv;

View File

@ -2695,10 +2695,16 @@ static void JS_Write(v8::FunctionCallbackInfo<v8::Value> const& args) {
if (args.Length() < 2) { if (args.Length() < 2) {
TRI_V8_THROW_EXCEPTION_USAGE("write(<filename>, <content>)"); TRI_V8_THROW_EXCEPTION_USAGE("write(<filename>, <content>)");
} }
#if _WIN32 // the wintendo needs utf16 filenames
TRI_Utf8ValueNFC name(args[0]); v8::String::Value str(args[0]);
std::wstring name {
if (*name == nullptr) { reinterpret_cast<wchar_t *>(*str),
static_cast<size_t>(str.length())};
#else
TRI_Utf8ValueNFC str(args[0]);
std::string name(*str, str.length());
#endif
if (name.length() == 0) {
TRI_V8_THROW_TYPE_ERROR("<filename> must be a string"); TRI_V8_THROW_TYPE_ERROR("<filename> must be a string");
} }
@ -2722,7 +2728,7 @@ static void JS_Write(v8::FunctionCallbackInfo<v8::Value> const& args) {
errno = 0; errno = 0;
// disable exceptions in the stream object: // disable exceptions in the stream object:
file.exceptions(std::ifstream::goodbit); file.exceptions(std::ifstream::goodbit);
file.open(*name, std::ios::out | std::ios::binary); file.open(name, std::ios::out | std::ios::binary);
if (file.is_open() && file.good()) { if (file.is_open() && file.good()) {
file.write(data, size); file.write(data, size);
@ -2752,7 +2758,7 @@ static void JS_Write(v8::FunctionCallbackInfo<v8::Value> const& args) {
errno = 0; errno = 0;
// disable exceptions in the stream object: // disable exceptions in the stream object:
file.exceptions(std::ifstream::goodbit); file.exceptions(std::ifstream::goodbit);
file.open(*name, std::ios::out | std::ios::binary); file.open(name, std::ios::out | std::ios::binary);
if (file.is_open() && file.good()) { if (file.is_open() && file.good()) {
file << *content; file << *content;

View File

@ -12,7 +12,7 @@
For more info read MiniZip_info.txt For more info read MiniZip_info.txt
*/ */
#include <unicode/unistr.h>
#include <stdlib.h> #include <stdlib.h>
#include "zlib.h" #include "zlib.h"
@ -108,10 +108,16 @@ win32_open64_file_funcA(voidpf opaque, const void* filename, int mode) {
win32_translate_open_mode(mode, &dwDesiredAccess, &dwCreationDisposition, win32_translate_open_mode(mode, &dwDesiredAccess, &dwCreationDisposition,
&dwShareMode, &dwFlagsAndAttributes); &dwShareMode, &dwFlagsAndAttributes);
if ((filename != NULL) && (dwDesiredAccess != 0)) if ((filename != NULL) && (dwDesiredAccess != 0)) {
hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, UnicodeString fn((LPSTR)filename);
dwCreationDisposition, dwFlagsAndAttributes, NULL); hFile = CreateFileW(fn.getTerminatedBuffer(),
dwDesiredAccess,
dwShareMode,
NULL,
dwCreationDisposition,
dwFlagsAndAttributes,
NULL);
}
return win32_build_iowin(hFile); return win32_build_iowin(hFile);
} }

View File

@ -50,6 +50,7 @@ private:
char const* ARGV0 = ""; char const* ARGV0 = "";
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
TRI_GET_ARGV(argc, argv);
int subargc = 0; int subargc = 0;
char **subargv = (char**)malloc(sizeof(char*) * argc); char **subargv = (char**)malloc(sizeof(char*) * argc);
bool logLineNumbers = false; bool logLineNumbers = false;