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_LIB_DEBUG "${CMAKE_BINARY_DIR}/bin/Debug/${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 ()
set(USE_RTTI ON CACHE BOOL "enable RTTI")
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_ZLIB "build with zlib" 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)
# Defaults currently different for GFLAGS.
# 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 result;
BOOL ret = DeleteFileA(fname.c_str());
BOOL ret = RX_DeleteFile(RX_FN(fname).c_str());
if(!ret) {
auto lastError = GetLastError();
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 s;
int result = truncate(fname.c_str(), size);
int result = rocksdb::port::Truncate(fname, size);
if (result != 0) {
s = IOError("Failed to truncate: " + fname, errno);
}
@ -151,8 +152,8 @@ Status WinEnvIO::NewSequentialFile(const std::string& fname,
{
IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA(
fname.c_str(), GENERIC_READ,
hFile = RX_CreateFile(
RX_FN(fname).c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, // Original fopen mode is "rb"
fileFlags, NULL);
@ -190,7 +191,7 @@ Status WinEnvIO::NewRandomAccessFile(const std::string& fname,
{
IOSTATS_TIMER_GUARD(open_nanos);
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,
NULL, OPEN_EXISTING, fileFlags, NULL);
}
@ -217,7 +218,7 @@ Status WinEnvIO::NewRandomAccessFile(const std::string& fname,
"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,
NULL); // Mapping name
@ -302,8 +303,8 @@ Status WinEnvIO::OpenWritableFile(const std::string& fname,
HANDLE hFile = 0;
{
IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA(
fname.c_str(),
hFile = RX_CreateFile(
RX_FN(fname).c_str(),
desired_access, // Access desired
shared_mode,
NULL, // Security attributes
@ -366,7 +367,7 @@ Status WinEnvIO::NewRandomRWFile(const std::string & fname,
{
IOSTATS_TIMER_GUARD(open_nanos);
hFile =
CreateFileA(fname.c_str(),
RX_CreateFile(RX_FN(fname).c_str(),
desired_access,
shared_mode,
NULL, // Security attributes
@ -399,8 +400,8 @@ Status WinEnvIO::NewMemoryMappedFileBuffer(const std::string & fname,
HANDLE hFile = INVALID_HANDLE_VALUE;
{
IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA(
fname.c_str(), GENERIC_READ | GENERIC_WRITE,
hFile = RX_CreateFile(
RX_FN(fname).c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
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);
}
HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE,
HANDLE hMap = RX_CreateFileMapping(hFile, NULL, PAGE_READWRITE,
0, // Whole file at its present length
0,
NULL); // Mapping name
@ -483,7 +484,7 @@ Status WinEnvIO::NewDirectory(const std::string& name,
// 0 - for access means read metadata
{
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,
NULL,
OPEN_EXISTING,
@ -509,8 +510,7 @@ Status WinEnvIO::FileExists(const std::string& fname) {
// which is consistent with _access() impl on windows
// but can be added
WIN32_FILE_ATTRIBUTE_DATA attrs;
if (FALSE == GetFileAttributesExA(fname.c_str(), GetFileExInfoStandard,
&attrs)) {
if (FALSE == RX_GetFileAttributesEx(RX_FN(fname).c_str(), GetFileExInfoStandard, &attrs)) {
auto lastError = GetLastError();
switch (lastError) {
case ERROR_ACCESS_DENIED:
@ -535,11 +535,12 @@ Status WinEnvIO::GetChildren(const std::string& dir,
result->clear();
std::vector<std::string> output;
WIN32_FIND_DATA data;
RX_WIN32_FIND_DATA data;
memset(&data, 0, sizeof(data));
std::string pattern(dir);
pattern.append("\\").append("*");
HANDLE handle = ::FindFirstFileExA(pattern.c_str(),
HANDLE handle = RX_FindFirstFileEx(RX_FN(pattern).c_str(),
FindExInfoBasic, // Do not want alternative name
&data,
FindExSearchNameMatch,
@ -572,8 +573,9 @@ Status WinEnvIO::GetChildren(const std::string& dir,
data.cFileName[MAX_PATH - 1] = 0;
while (true) {
output.emplace_back(data.cFileName);
BOOL ret =- ::FindNextFileA(handle, &data);
auto x = RX_FILESTRING(data.cFileName, RX_FNLEN(data.cFileName));
output.emplace_back(FN_TO_RX(x));
BOOL ret =- RX_FindNextFile(handle, &data);
// If the function fails the return value is zero
// and non-zero otherwise. Not TRUE or FALSE.
if (ret == FALSE) {
@ -588,8 +590,7 @@ Status WinEnvIO::GetChildren(const std::string& dir,
Status WinEnvIO::CreateDir(const std::string& name) {
Status result;
BOOL ret = CreateDirectoryA(name.c_str(), NULL);
BOOL ret = RX_CreateDirectory(RX_FN(name).c_str(), NULL);
if (!ret) {
auto lastError = GetLastError();
result = IOErrorFromWindowsError(
@ -606,7 +607,7 @@ Status WinEnvIO::CreateDirIfMissing(const std::string& name) {
return result;
}
BOOL ret = CreateDirectoryA(name.c_str(), NULL);
BOOL ret = RX_CreateDirectory(RX_FN(name).c_str(), NULL);
if (!ret) {
auto lastError = GetLastError();
if (lastError != ERROR_ALREADY_EXISTS) {
@ -622,7 +623,7 @@ Status WinEnvIO::CreateDirIfMissing(const std::string& name) {
Status WinEnvIO::DeleteDir(const std::string& name) {
Status result;
BOOL ret = RemoveDirectoryA(name.c_str());
BOOL ret = RX_RemoveDirectory(RX_FN(name).c_str());
if (!ret) {
auto lastError = GetLastError();
result = IOErrorFromWindowsError("Failed to remove dir: " + name, lastError);
@ -635,7 +636,7 @@ Status WinEnvIO::GetFileSize(const std::string& fname,
Status s;
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;
file_size.HighPart = attrs.nFileSizeHigh;
file_size.LowPart = attrs.nFileSizeLow;
@ -670,7 +671,7 @@ Status WinEnvIO::GetFileModificationTime(const std::string& fname,
Status s;
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);
} else {
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
// 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();
std::string text("Failed to rename: ");
@ -704,7 +705,7 @@ Status WinEnvIO::LinkFile(const std::string& src,
const std::string& target) {
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();
std::string text("Failed to link: ");
@ -719,7 +720,7 @@ Status WinEnvIO::LinkFile(const std::string& src,
Status WinEnvIO::NumFileLinks(const std::string& fname,
uint64_t* count) {
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,
NULL,
OPEN_EXISTING,
@ -758,7 +759,7 @@ Status WinEnvIO::AreFilesSame(const std::string& first,
}
// 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,
NULL,
OPEN_EXISTING,
@ -773,7 +774,7 @@ Status WinEnvIO::AreFilesSame(const std::string& first,
}
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,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, // make opening folders possible
@ -835,7 +836,7 @@ Status WinEnvIO::LockFile(const std::string& lockFname,
HANDLE hFile = 0;
{
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,
FILE_ATTRIBUTE_NORMAL, NULL);
}
@ -898,8 +899,8 @@ Status WinEnvIO::NewLogger(const std::string& fname,
HANDLE hFile = 0;
{
IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA(
fname.c_str(), GENERIC_WRITE,
hFile = RX_CreateFile(
RX_FN(fname).c_str(), GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_DELETE, // In RocksDb log files are
// renamed and deleted before
// 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
// absolute path
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;
return Status::OK();
}
std::string result;
RX_FILESTRING result;
result.resize(MAX_PATH);
// Hopefully no changes the current directory while we do this
// 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) {
auto lastError = GetLastError();
return IOErrorFromWindowsError("Failed to get current working directory",
@ -1010,8 +1011,9 @@ Status WinEnvIO::GetAbsolutePath(const std::string& db_path,
}
result.resize(len);
result.swap(*output_path);
std::string res = FN_TO_RX(result);
res.swap(*output_path);
return Status::OK();
}
@ -1076,7 +1078,7 @@ EnvOptions WinEnvIO::OptimizeForManifestRead(
// Returns true iff the named directory exists and is a directory.
bool WinEnvIO::DirExists(const std::string& dname) {
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 false;
@ -1085,7 +1087,7 @@ bool WinEnvIO::DirExists(const std::string& dname) {
size_t WinEnvIO::GetSectorSize(const std::string& fname) {
size_t sector_size = kSectorSize;
if (PathIsRelativeA(fname.c_str())) {
if (RX_PathIsRelative(RX_FN(fname).c_str())) {
return sector_size;
}

View File

@ -26,11 +26,28 @@
#include <exception>
#include <chrono>
#ifdef ROCKSDB_WINDOWS_UTF8_FILENAMES
// utf8 <-> utf16
#include <string>
#include <locale>
#include <codecvt>
#endif
#include "util/logging.h"
namespace rocksdb {
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 */) {
using namespace std::chrono;
@ -110,7 +127,7 @@ void InitOnce(OnceType* once, void (*initializer)()) {
struct DIR {
HANDLE handle_;
bool firstread_;
WIN32_FIND_DATA data_;
RX_WIN32_FIND_DATA data_;
dirent entry_;
DIR() : handle_(INVALID_HANDLE_VALUE),
@ -137,7 +154,7 @@ DIR* opendir(const char* name) {
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
&dir->data_,
FindExSearchNameMatch,
@ -148,8 +165,9 @@ DIR* opendir(const char* name) {
return nullptr;
}
RX_FILESTRING x(dir->data_.cFileName, RX_FNLEN(dir->data_.cFileName));
strcpy_s(dir->entry_.d_name, sizeof(dir->entry_.d_name),
dir->data_.cFileName);
FN_TO_RX(x).c_str());
return dir.release();
}
@ -165,14 +183,15 @@ struct dirent* readdir(DIR* dirp) {
return &dirp->entry_;
}
auto ret = ::FindNextFileA(dirp->handle_, &dirp->data_);
auto ret = RX_FindNextFile(dirp->handle_, &dirp->data_);
if (ret == 0) {
return nullptr;
}
RX_FILESTRING x(dirp->data_.cFileName, RX_FNLEN(dirp->data_.cFileName));
strcpy_s(dirp->entry_.d_name, sizeof(dirp->entry_.d_name),
dirp->data_.cFileName);
FN_TO_RX(x).c_str());
return &dirp->entry_;
}
@ -182,11 +201,15 @@ int closedir(DIR* dirp) {
return 0;
}
int truncate(const char* path, int64_t len) {
int truncate(const char* path, int64_t length) {
if (path == nullptr) {
errno = EFAULT;
return -1;
}
return rocksdb::port::Truncate(path, length);
}
int Truncate(std::string path, int64_t len) {
if (len < 0) {
errno = EINVAL;
@ -194,7 +217,7 @@ int truncate(const char* path, int64_t len) {
}
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,
NULL, // Security attrs
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
// feel space with zeros in case the file is extended.
int truncate(const char* path, int64_t length);
int Truncate(std::string path, int64_t length);
void Crash(const std::string& srcfile, int srcline);
extern int GetMaxOpenFiles();
std::string utf16_to_utf8(const std::wstring& utf16);
std::wstring utf8_to_utf16(const std::string& utf8);
} // 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_create;
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 "StripSlashes.nsh"
!include "xcopy.nsh"
!include "Utf8Converter.nsh"
; !include "GetTime.nsh"
;--------------------------------
; get commandline parameters
@ -67,6 +68,7 @@ Var BackupPath
VAR TRI_INSTALL_SERVICE ; x bool
VAR TRI_INSTALL_SCOPE_ALL ; x bool => All / ThisUser
Var newCfgValues ; keep new config file values
Var newCfgValuesUtf8 ; translated version of the content
Var newCfgValuesFile ; write them to a temporary file...
Var ServiceUp ; did the service start?
!define TEMP1 $R0 ;Temp variable
@ -207,8 +209,10 @@ Function un.ReadSettings
;MessageBox MB_OK "Add to path: $ADD_TO_PATH"
ReadRegStr $ADD_DESKTOP_ICON SHCTX "${TRI_UNINSTALL_REG_PATH}" "InstallToDesktop"
ReadINIStr $DATADIR "$INSTDIR\${ARANGO_INI}" "database" "directory"
ReadINIStr $APPDIR "$INSTDIR\${ARANGO_INI}" "javascript" "app-path"
ReadINIStr $newCfgValuesUtf8 "$INSTDIR\${ARANGO_INI}" "database" "directory"
${Utf8ToAnsi} $newCfgValuesUtf8 $DATADIR
ReadINIStr $newCfgValuesUtf8 "$INSTDIR\${ARANGO_INI}" "javascript" "app-path"
${Utf8ToAnsi} $newCfgValuesUtf8 $APPDIR
FunctionEnd
@ -948,9 +952,10 @@ Section "-Core installation"
; StrCpy $ini_LOGFILE "[log]$\r$\nfile = $LOGFILE$\r$\n"
;${EndIf}
StrCpy $newCfgValues "$ini_APPDIR$ini_DATADIR[server]$\r$\nstorage-engine = $STORAGE_ENGINE$\r$\n"
${AnsiToUtf8} $newCfgValues $newCfgValuesUtf8
StrCpy $newCfgValuesFile "$INSTDIR\etc\arangodb3\newValues.ini"
FileOpen $4 "$newCfgValuesFile" w
FileWrite $4 "$newCfgValues"
FileWrite $4 "$newCfgValuesUtf8"
FileClose $4
; Alter the shipped file and insert the values from above:
push "$newCfgValuesFile"

View File

@ -24,8 +24,6 @@
#include "ServerState.h"
#include <iomanip>
#include <iostream>
#include <sstream>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
@ -451,19 +449,24 @@ std::string ServerState::generatePersistedId(RoleEnum const& role) {
}
std::string ServerState::getPersistedId() {
std::string uuidFilename = getUuidFilename();
if (hasPersistedId()) {
std::string uuidFilename = getUuidFilename();
std::ifstream ifs(uuidFilename);
std::string id;
if (ifs.is_open()) {
std::getline(ifs, id);
ifs.close();
return id;
try {
auto uuidBuf = arangodb::basics::FileUtils::slurp(uuidFilename);
basics::StringUtils::trimInPlace(uuidBuf);
if (!uuidBuf.empty()) {
return uuidBuf;
}
}
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();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,12 +22,11 @@
#include "DaemonFeature.h"
#include <fstream>
#include <iostream>
#include <thread>
#include <chrono>
#include "Basics/FileUtils.h"
#include "Basics/StringUtils.h"
#include "Logger/LogAppender.h"
#include "Logger/Logger.h"
#include "Logger/LoggerFeature.h"
@ -147,15 +146,30 @@ void DaemonFeature::checkPidFile() {
} else if (FileUtils::exists(_pidFile) && FileUtils::size(_pidFile) > 0) {
LOG_TOPIC(INFO, Logger::STARTUP) << "pid-file '" << _pidFile
<< "' 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 (f) {
if (!oldPidS.empty()) {
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) {
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "pid-file '" << _pidFile
<< "' is unreadable";
@ -316,15 +330,14 @@ void DaemonFeature::remapStandardFileDescriptors() {
}
void DaemonFeature::writePidFile(int pid) {
std::ofstream out(_pidFile.c_str(), std::ios::trunc);
if (!out) {
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "cannot write pid-file '"
<< _pidFile << "'";
FATAL_ERROR_EXIT();
try {
arangodb::basics::FileUtils::spit(_pidFile, std::to_string(pid), true);
}
catch (arangodb::basics::Exception const& ex) {
LOG_TOPIC(FATAL, arangodb::Logger::FIXME) << "cannot write pid-file '"
<< _pidFile << "' - "
<< ex.what();
}
out << 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& path,
std::string const& binaryName) {
char const* icuDataEnv = getenv("ICU_DATA");
std::string fn("icudtl.dat");
if (icuDataEnv != nullptr) {
path = FileUtils::buildFilename(icuDataEnv, fn);
}
TRI_GETENV("ICU_DATA", path);
if (path.empty() || !TRI_IsRegularFile(path.c_str())) {
if (!path.empty()) {
LOG_TOPIC(WARN, arangodb::Logger::FIXME)
@ -118,7 +113,8 @@ void* LanguageFeature::prepareIcu(std::string const& binaryPath,
#ifndef _WIN32
setenv("ICU_DATA", icu_path.c_str(), 1);
#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
}
}

View File

@ -30,6 +30,7 @@
#ifdef TRI_HAVE_DIRECT_H
#include <direct.h>
#endif
#include <unicode/unistr.h>
#include "Basics/Exceptions.h"
#include "Basics/OpenFilesTracker.h"
@ -38,15 +39,6 @@
#include "Basics/tri-strings.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 basics {
@ -244,21 +236,6 @@ bool remove(std::string const& fileName, int* errorNumber) {
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) {
if (errorNumber != nullptr) {
*errorNumber = 0;
@ -299,17 +276,22 @@ bool copyRecursive(std::string const& source, std::string const& target,
bool copyDirectoryRecursive(std::string const& source,
std::string const& target, std::string& error) {
char* fn = nullptr;
bool rc = true;
auto isSubDirectory = [](std::string const& name) -> bool {
return isDirectory(name);
};
#ifdef TRI_HAVE_WIN32_LIST_FILES
struct _finddata_t oneItem;
struct _wfinddata_t oneItem;
intptr_t handle;
std::string rcs;
std::string filter = source + "\\*";
handle = _findfirst(filter.c_str(), &oneItem);
UnicodeString f(filter.c_str());
handle = _wfindfirst(f.getTerminatedBuffer(), &oneItem);
if (handle == -1) {
error = "directory " + source + "not found";
@ -317,6 +299,11 @@ bool copyDirectoryRecursive(std::string const& source,
}
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
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
// thread-safety formally, and in addition obsolete readdir_r() altogether
while ((oneItem = (readdir(filedir))) != nullptr) {
fn = oneItem->d_name;
#endif
// Now iterate over the items.
// check its not the pointer to the upper directory:
if (!strcmp(TRI_DIR_FN(oneItem), ".") ||
!strcmp(TRI_DIR_FN(oneItem), "..")) {
if (!strcmp(fn, ".") ||
!strcmp(fn, "..")) {
continue;
}
std::string dst = target + TRI_DIR_SEPARATOR_STR + TRI_DIR_FN(oneItem);
std::string src = source + TRI_DIR_SEPARATOR_STR + TRI_DIR_FN(oneItem);
std::string dst = target + TRI_DIR_SEPARATOR_STR + fn;
std::string src = source + TRI_DIR_SEPARATOR_STR + fn;
// Handle subdirectories:
if (isSubDirectory(src)) {
@ -370,7 +358,7 @@ bool copyDirectoryRecursive(std::string const& source,
}
}
#ifdef TRI_HAVE_WIN32_LIST_FILES
} while (_findnext(handle, &oneItem) != -1);
} while (_wfindnext(handle, &oneItem) != -1);
_findclose(handle);
@ -386,12 +374,15 @@ std::vector<std::string> listFiles(std::string const& directory) {
std::vector<std::string> result;
#ifdef TRI_HAVE_WIN32_LIST_FILES
char* fn = nullptr;
struct _finddata_t fd;
struct _wfinddata_t oneItem;
intptr_t handle;
std::string rcs;
std::string filter = directory + "\\*";
handle = _findfirst(filter.c_str(), &fd);
UnicodeString f(filter.c_str());
handle = _wfindfirst(f.getTerminatedBuffer(), &oneItem);
if (handle == -1) {
TRI_set_errno(TRI_ERROR_SYS_ERROR);
@ -402,10 +393,18 @@ std::vector<std::string> listFiles(std::string const& directory) {
}
do {
if (strcmp(fd.name, ".") != 0 && strcmp(fd.name, "..") != 0) {
result.push_back(fd.name);
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();
if (!strcmp(fn, ".") ||
!strcmp(fn, "..")) {
continue;
}
} while (_findnext(handle, &fd) != -1);
} while (_wfindnext(handle, &oneItem) != -1);
_findclose(handle);
@ -578,7 +577,8 @@ static void throwProgramError(std::string const& filename) {
std::string slurpProgram(std::string const& program) {
#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
FILE* fp = popen(program.c_str(), "r");
#endif

View File

@ -72,10 +72,6 @@ void spit(std::string const& filename, StringBuffer const& content,
// returns true if a file could be removed
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
bool createDirectory(std::string const& name, int* errorNumber = nullptr);
bool createDirectory(std::string const& name, int mask, int* errorNumber = nullptr);

View File

@ -28,6 +28,7 @@
#include <Shlwapi.h>
#include <chrono>
#include <thread>
#include <unicode/locid.h>
#endif
#include <algorithm>
@ -164,14 +165,10 @@ static void ListTreeRecursively(char const* full, char const* path,
////////////////////////////////////////////////////////////////////////////////
static std::string LocateConfigDirectoryEnv() {
char const* v = getenv("ARANGODB_CONFIG_PATH");
if (v == nullptr) {
std::string r;
if (!TRI_GETENV("ARANGODB_CONFIG_PATH", r)) {
return std::string();
}
std::string r(v);
NormalizePath(r);
while (!r.empty() && IsDirSeparatorChar(r[r.size() - 1])) {
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 res;
#ifdef _WIN32
res = _chmod(path, static_cast<int>(mode));
UnicodeString wpath(path);
res = _wchmod(wpath.getTerminatedBuffer(), static_cast<int>(mode));
#else
res = chmod(path, mode);
#endif
@ -655,18 +653,26 @@ std::vector<std::string> TRI_FilesDirectory(char const* path) {
std::string filter(path);
filter.append("\\*");
struct _finddata_t fd;
intptr_t handle = _findfirst(filter.c_str(), &fd);
struct _wfinddata_t fd;
UnicodeString wfilter(filter.c_str());
intptr_t handle = _wfindfirst(wfilter.getTerminatedBuffer(), &fd);
if (handle == -1) {
return result;
}
std::string ufn;
UnicodeString fn;
do {
if (strcmp(fd.name, ".") != 0 && strcmp(fd.name, "..") != 0) {
result.emplace_back(fd.name);
if (wcscmp(fd.name, L".") != 0 && wcscmp(fd.name, L"..") != 0) {
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);
@ -724,7 +730,11 @@ int TRI_RenameFile(char const* old, char const* filename, long* systemError,
TRI_ERRORBUF;
#ifdef _WIN32
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);
if (!moveResult) {
@ -956,8 +966,9 @@ int TRI_CreateLockFile(char const* filename) {
return TRI_ERROR_NO_ERROR;
}
}
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);
if (fd == INVALID_HANDLE_VALUE) {
@ -1467,13 +1478,13 @@ std::string TRI_BinaryName(char const* argv0) {
std::string TRI_LocateBinaryPath(char const* argv0) {
#if _WIN32
char buff[4096];
int res = GetModuleFileName(NULL, buff, sizeof(buff));
wchar_t buff[4096];
int res = GetModuleFileNameW(NULL, buff, sizeof(buff));
if (res != 0) {
buff[4095] = '\0';
char* q = buff + res;
wchar_t* q = buff + res;
while (buff < q) {
if (*q == '\\' || *q == '/') {
@ -1484,7 +1495,13 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
--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();
@ -1506,10 +1523,9 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
// check PATH variable
else {
p = getenv("PATH");
if (p != nullptr) {
std::vector<std::string> files = basics::StringUtils::split(std::string(p), ':', '\0');
std::string pv;
if (TRI_GETENV("PATH", pv)) {
std::vector<std::string> files = basics::StringUtils::split(pv, ':', '\0');
for (auto const& prefix : files) {
std::string full;
@ -1659,7 +1675,11 @@ bool TRI_CopyFile(std::string const& src, std::string const& dst,
std::string& error) {
#ifdef _WIN32
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) {
TRI_SYSTEM_ERROR();
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
std::string TRI_HomeDirectory() {
char const* drive = getenv("HOMEDRIVE");
char const* path = getenv("HOMEPATH");
std::string drive;
std::string path;
if (drive == nullptr || path == nullptr) {
if (! TRI_GETENV("HOMEDRIVE", drive) ||
! TRI_GETENV("HOMEPATH", path)) {
return std::string();
}
return std::string(drive) + std::string(path);
return drive + path;
}
#else
@ -1833,7 +1854,7 @@ int TRI_Crc32File(char const* path, uint32_t* crc) {
return TRI_ERROR_OUT_OF_MEMORY;
}
fin = fopen(path, "rb");
fin = TRI_FOPEN(path, "rb");
if (fin == nullptr) {
TRI_Free(buffer);
@ -1901,7 +1922,7 @@ static std::string getTempPath() {
// ..........................................................................
#define LOCAL_MAX_PATH_BUFFER 2049
TCHAR tempPathName[LOCAL_MAX_PATH_BUFFER];
wchar_t tempPathName[LOCAL_MAX_PATH_BUFFER];
DWORD dwReturnValue = 0;
// ..........................................................................
// 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 Windows directory.
*/
dwReturnValue = GetTempPath(LOCAL_MAX_PATH_BUFFER, tempPathName);
dwReturnValue = GetTempPathW(LOCAL_MAX_PATH_BUFFER, tempPathName);
if ((dwReturnValue > LOCAL_MAX_PATH_BUFFER) || (dwReturnValue == 0)) {
// 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;
}
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
// 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) {
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 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);
}
return rc;
@ -2118,7 +2147,7 @@ int TRI_GetTempName(char const* directory, std::string& result, bool createFile,
errorMessage = std::string("Tempfile already exists! ") + filename;
} else {
if (createFile) {
FILE* fd = fopen(filename.c_str(), "wb");
FILE* fd = TRI_FOPEN(filename.c_str(), "wb");
if (fd != nullptr) {
fclose(fd);
@ -2313,7 +2342,8 @@ int TRI_CreateDatafile(std::string const& filename, size_t maximalSize) {
bool TRI_PathIsAbsolute(std::string const& path) {
#if _WIN32
return !PathIsRelative(path.c_str());
UnicodeString upath(path.c_str(), (uint16_t) path.length());
return !PathIsRelativeW(upath.getTerminatedBuffer());
#else
return (!path.empty()) && path.c_str()[0] == '/';
#endif
@ -2334,3 +2364,27 @@ void TRI_InitializeFiles() {
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();
////////////////////////////////////////////////////////////////////////////////
/// @brief if which is found, value is overwriten, true returned.
////////////////////////////////////////////////////////////////////////////////
bool TRI_GETENV(char const* which, std::string &value);
#endif

View File

@ -172,6 +172,7 @@
#define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read
#define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat
@ -192,6 +193,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \
{}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets
@ -329,6 +331,7 @@
#define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read
#define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat
@ -349,6 +352,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \
{}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets
@ -473,6 +477,7 @@
#define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read
#define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat
@ -493,6 +498,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \
{}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets
@ -631,6 +637,7 @@
#define TRI_LSEEK ::lseek
#define TRI_MKDIR(a, b) ::mkdir((a), (b))
#define TRI_OPEN(a, b) ::open((a), (b))
#define TRI_FOPEN(a, b) ::fopen((a), (b))
#define TRI_READ ::read
#define TRI_RMDIR ::rmdir
#define TRI_STAT ::stat
@ -651,6 +658,7 @@
#define TRI_LAST_ERROR_STR ::strerror(errno)
#define TRI_SYSTEM_ERROR() \
{}
#define TRI_GET_ARGV(ARGC, ARGV)
// sockets
@ -704,7 +712,6 @@
#include <WinSock2.h>
#include <io.h>
#include <stdio.h>
// available include files
#define TRI_HAVE_DIRECT_H 1
@ -829,18 +836,13 @@ typedef unsigned char bool;
#define O_RDONLY _O_RDONLY
#define TRI_CHDIR ::_chdir
#define TRI_CLOSE ::_close
#define TRI_CREATE(a, b, c) TRI_createFile((a), (b), (c))
#define TRI_FSTAT ::_fstat64
#define TRI_GETCWD ::_getcwd
#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_READ ::_read
#define TRI_RMDIR ::_rmdir
#define TRI_STAT ::_stat64
#define TRI_UNLINK ::_unlink
#define TRI_WRITE ::_write
#define TRI_FDOPEN(a, b) ::_fdopen((a), (b))
@ -853,6 +855,17 @@ typedef unsigned char bool;
#define TRI_ERRORBUF char windowsErrorBuf[256] = "";
#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.

View File

@ -44,6 +44,7 @@
#ifdef _WIN32
#include <Psapi.h>
#include <TlHelp32.h>
#include <unicode/unistr.h>
#endif
#include "Logger/Logger.h"
@ -326,20 +327,57 @@ static int appendQuotedArg(TRI_string_buffer_t* buf, char const* p) {
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;
int err = TRI_ERROR_NO_ERROR;
char* res;
buf = TRI_CreateStringBuffer();
if (buf == nullptr) {
return nullptr;
}
std::wstring res;
if (( external->_executable.find('/') == std::string::npos) &&
( external->_executable.find('\\') == std::string::npos)) {
// oK, this is a binary without path, start the lookup.
// This will most probably break with non-ascii paths.
char buf[MAX_PATH];
char *pBuf;
DWORD n;
@ -349,34 +387,32 @@ static char* makeWindowsArgs(ExternalProcess* external) {
}
}
TRI_ReserveStringBuffer(buf, 1024);
err = appendQuotedArg(buf, external->_executable.c_str());
UnicodeString uwargs(external->_executable.c_str());
err = wAppendQuotedArg(res, uwargs.getTerminatedBuffer());
if (err != TRI_ERROR_NO_ERROR) {
TRI_FreeStringBuffer(buf);
return nullptr;
}
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) {
TRI_FreeStringBuffer(buf);
return nullptr;
}
err = appendQuotedArg(buf, external->_arguments[i]);
}
res = TRI_StealStringBuffer(buf);
TRI_FreeStringBuffer(buf);
return res;
}
static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
char* args;
std::wstring args;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
STARTUPINFOW siStartInfo;
BOOL bFuncRetn = FALSE;
TRI_ERRORBUF;
args = makeWindowsArgs(external);
if (args == nullptr) {
if (args.length() == 0) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "execute of '" << external->_executable
<< "' failed making args";
return false;
@ -386,8 +422,8 @@ static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
// set up members of the STARTUPINFO structure
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
ZeroMemory(&siStartInfo, sizeof(STARTUPINFOW));
siStartInfo.cb = sizeof(STARTUPINFOW);
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.hStdInput = rd ? rd : nullptr;
@ -395,18 +431,16 @@ static bool startProcess(ExternalProcess* external, HANDLE rd, HANDLE wr) {
siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
// create the child process
bFuncRetn = CreateProcess(NULL,
args, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NEW_PROCESS_GROUP, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
TRI_Free(args);
bFuncRetn = CreateProcessW(NULL,
(LPWSTR)args.c_str(), // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
CREATE_NEW_PROCESS_GROUP, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (bFuncRetn == FALSE) {
TRI_SYSTEM_ERROR();

View File

@ -26,6 +26,7 @@
#include "Basics/files.h"
#include "Basics/FileUtils.h"
#include "Basics/tri-strings.h"
#include "Basics/Common.h"
#include "Zip/unzip.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
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
if (fout == nullptr && !skipPaths &&
@ -166,7 +167,7 @@ static int ExtractCurrentFile(unzFile uf, void* buffer, size_t const bufferSize,
*(filenameWithoutPath - 1) = c;
// try again
fout = fopen(fullPath.c_str(), "wb");
fout = TRI_FOPEN(fullPath.c_str(), "wb");
} else if (fout == nullptr) {
// try to create the target directory recursively
// 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
fout = fopen(fullPath.c_str(), "wb");
fout = TRI_FOPEN(fullPath.c_str(), "wb");
}
if (fout == nullptr) {
@ -340,7 +341,7 @@ int TRI_ZipFile(char const* filename, char const* dir,
break;
}
FILE* fin = fopen(fullfile.c_str(), "rb");
FILE* fin = TRI_FOPEN(fullfile.c_str(), "rb");
if (fin == nullptr) {
break;
@ -394,7 +395,7 @@ int TRI_Adler32(char const* filename, uint32_t& checksum) {
}
TRI_DEFER(TRI_CLOSE(fd));
struct TRI_STAT statbuf;
TRI_stat_t statbuf;
int res = TRI_FSTAT(fd, &statbuf);
if (res < 0) {
TRI_ERRORBUF;

View File

@ -24,6 +24,15 @@
#include <errno.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"
@ -33,14 +42,13 @@
#include <crtdbg.h>
#include <atlstr.h>
#include <VersionHelpers.h>
#include <unicode/uchar.h>
#include <unicode/unistr.h>
#include "Logger/Logger.h"
#include "Basics/files.h"
#include "Basics/StringUtils.h"
#include "Basics/tri-strings.h"
#include "Basics/directories.h"
#include "Basics/Common.h"
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) {
HANDLE fileHandle;
int fileDescriptor;
UnicodeString fn(filename);
fileHandle =
CreateFileA(filename, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
(openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW, 0, NULL);
CreateFileW(fn.getTerminatedBuffer(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
(openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW,
0,
NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
return -1;
@ -228,8 +241,12 @@ int TRI_OPEN_WIN32(char const* filename, int openFlags) {
break;
}
fileHandle = CreateFileA(
filename, mode, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
UnicodeString fn(filename);
fileHandle = CreateFileW(fn.getTerminatedBuffer(),
mode,
FILE_SHARE_DELETE |
FILE_SHARE_READ |
FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
@ -241,6 +258,64 @@ int TRI_OPEN_WIN32(char const* filename, int openFlags) {
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
////////////////////////////////////////////////////////////////////////////////
@ -411,7 +486,7 @@ int TRI_MapSystemError(DWORD error) {
static HANDLE hEventLog = INVALID_HANDLE_VALUE;
bool TRI_InitWindowsEventLog(void) {
hEventLog = RegisterEventSource(NULL, "ArangoDB");
hEventLog = RegisterEventSourceW(NULL, L"ArangoDB");
if (NULL == hEventLog) {
// well, fail then.
return false;
@ -424,13 +499,6 @@ void TRI_CloseWindowsEventlog(void) {
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...
#define MSG_INVALID_COMMAND ((DWORD)0xC0020100L)
#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());
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...
if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY,
MSG_INVALID_COMMAND, NULL, 4, 0, (LPCSTR*)logBuffers,
NULL)) {
if (!ReportEventW(hEventLog,
EVENTLOG_ERROR_TYPE,
UI_CATEGORY,
MSG_INVALID_COMMAND,
NULL,
4, 0,
buffers, NULL)) {
// 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);
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...
if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, UI_CATEGORY,
MSG_INVALID_COMMAND, NULL, 4, 0, (LPCSTR*)logBuffers,
NULL)) {
if (!ReportEventW(hEventLog,
EVENTLOG_ERROR_TYPE,
UI_CATEGORY,
MSG_INVALID_COMMAND,
NULL,
4, 0,
buffers, NULL)) {
// well, fail then...
}
}
@ -656,3 +758,29 @@ std::string getFileNameFromHandle(HANDLE fileHandle) {
}
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");
FileUtils::remove(backup);
FileUtils::rename(filename, backup);
TRI_RenameFile(filename.c_str(), backup.c_str());
// open new log file
int fd = TRI_TRACKED_CREATE_FILE(filename.c_str(),
@ -210,7 +210,7 @@ void LogAppenderFile::reopenAll() {
S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
FileUtils::rename(backup, filename);
TRI_RenameFile(backup.c_str(), filename.c_str());
continue;
}

View File

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

View File

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

View File

@ -2695,10 +2695,16 @@ static void JS_Write(v8::FunctionCallbackInfo<v8::Value> const& args) {
if (args.Length() < 2) {
TRI_V8_THROW_EXCEPTION_USAGE("write(<filename>, <content>)");
}
TRI_Utf8ValueNFC name(args[0]);
if (*name == nullptr) {
#if _WIN32 // the wintendo needs utf16 filenames
v8::String::Value str(args[0]);
std::wstring name {
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");
}
@ -2722,7 +2728,7 @@ static void JS_Write(v8::FunctionCallbackInfo<v8::Value> const& args) {
errno = 0;
// disable exceptions in the stream object:
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()) {
file.write(data, size);
@ -2752,7 +2758,7 @@ static void JS_Write(v8::FunctionCallbackInfo<v8::Value> const& args) {
errno = 0;
// disable exceptions in the stream object:
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()) {
file << *content;

View File

@ -12,7 +12,7 @@
For more info read MiniZip_info.txt
*/
#include <unicode/unistr.h>
#include <stdlib.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,
&dwShareMode, &dwFlagsAndAttributes);
if ((filename != NULL) && (dwDesiredAccess != 0))
hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL,
dwCreationDisposition, dwFlagsAndAttributes, NULL);
if ((filename != NULL) && (dwDesiredAccess != 0)) {
UnicodeString fn((LPSTR)filename);
hFile = CreateFileW(fn.getTerminatedBuffer(),
dwDesiredAccess,
dwShareMode,
NULL,
dwCreationDisposition,
dwFlagsAndAttributes,
NULL);
}
return win32_build_iowin(hFile);
}

View File

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