Merge pull request #343 from kiwix/fix_datadir_windows

Fix datadir windows
This commit is contained in:
Matthieu Gautier 2020-04-15 10:18:51 +02:00 committed by GitHub
commit 5d98a6964e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 85 additions and 32 deletions

View File

@ -18,6 +18,7 @@
*/ */
#include "tools/pathTools.h" #include "tools/pathTools.h"
#include <stdexcept>
#ifdef __APPLE__ #ifdef __APPLE__
#include <limits.h> #include <limits.h>
@ -42,12 +43,16 @@
#include <algorithm> #include <algorithm>
#ifdef _WIN32 #ifdef _WIN32
#define SEPARATOR "\\" # define SEPARATOR "\\"
# include <io.h>
#else #else
#define SEPARATOR "/" # define SEPARATOR "/"
#include <unistd.h> # include <unistd.h>
# include <sys/stat.h>
#endif #endif
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef PATH_MAX #ifndef PATH_MAX
@ -227,14 +232,33 @@ std::string getFileSizeAsString(const std::string& path)
std::string getFileContent(const std::string& path) std::string getFileContent(const std::string& path)
{ {
std::ifstream f(path, std::ios::in|std::ios::ate); #ifdef _WIN32
auto wpath = Utf8ToWide(path);
auto fd = _wopen(wpath.c_str(), _O_RDONLY | _O_BINARY);
#else
auto fd = open(path.c_str(), O_RDONLY);
#endif
std::string content; std::string content;
if (f.is_open()) { if (fd != -1) {
auto size = f.tellg(); #ifdef _WIN32
content.reserve(size); auto size = _lseeki64(fd, 0, SEEK_END);
f.seekg(0, std::ios::beg); #else
content.assign((std::istreambuf_iterator<char>(f)), auto size = lseek(fd, 0, SEEK_END);
std::istreambuf_iterator<char>()); #endif
content.resize(size);
#ifdef _WIN32
_lseeki64(fd, 0, SEEK_SET);
#else
lseek(fd, 0, SEEK_SET);
#endif
auto p = (char*)content.data();
while (size) {
auto readsize = size > 2048 ? 2048 : size;
readsize = ::read(fd, p, readsize);
p += readsize;
size -= readsize;
}
close(fd);
} }
return content; return content;
} }
@ -287,22 +311,22 @@ std::string makeTmpDirectory()
/* Try to create a link and if does not work then make a copy */ /* Try to create a link and if does not work then make a copy */
bool copyFile(const std::string& sourcePath, const std::string& destPath) bool copyFile(const std::string& sourcePath, const std::string& destPath)
{ {
#ifdef _WIN32
return CopyFileW(Utf8ToWide(sourcePath).c_str(), Utf8ToWide(destPath).c_str(), 1);
#else
try { try {
#ifndef _WIN32
if (link(sourcePath.c_str(), destPath.c_str()) != 0) { if (link(sourcePath.c_str(), destPath.c_str()) != 0) {
#endif
std::ifstream infile(sourcePath.c_str(), std::ios_base::binary); std::ifstream infile(sourcePath.c_str(), std::ios_base::binary);
std::ofstream outfile(destPath.c_str(), std::ios_base::binary); std::ofstream outfile(destPath.c_str(), std::ios_base::binary);
outfile << infile.rdbuf(); outfile << infile.rdbuf();
#ifndef _WIN32
} }
#endif
} catch (std::exception& e) { } catch (std::exception& e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return false; return false;
} }
return true; return true;
#endif
} }
std::string getExecutablePath(bool realPathOnly) std::string getExecutablePath(bool realPathOnly)
@ -341,10 +365,21 @@ std::string getExecutablePath(bool realPathOnly)
bool writeTextFile(const std::string& path, const std::string& content) bool writeTextFile(const std::string& path, const std::string& content)
{ {
std::ofstream file; #ifdef _WIN32
file.open(path.c_str()); auto wpath = Utf8ToWide(path);
file << content; auto fd = _wopen(wpath.c_str(), _O_WRONLY | _O_CREAT | _O_TRUNC, S_IWRITE);
file.close(); #else
auto fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
#endif
if (fd == -1)
return false;
if (write(fd, content.c_str(), content.size()) != (long)content.size()) {
close(fd);
return false;
}
close(fd);
return true; return true;
} }
@ -364,30 +399,48 @@ std::string getCurrentDirectory()
std::string getDataDirectory() std::string getDataDirectory()
{ {
// Try to get the dataDir from the `KIWIX_DATA_DIR` env var
#ifdef _WIN32 #ifdef _WIN32
char* cDataDir = ::getenv("APPDATA"); wchar_t* cDataDir = ::_wgetenv(L"KIWIX_DATA_DIR");
if (cDataDir != nullptr) {
return WideToUtf8(cDataDir);
}
#else #else
char* cDataDir = ::getenv("KIWIX_DATA_DIR"); char* cDataDir = ::getenv("KIWIX_DATA_DIR");
#endif if (cDataDir != nullptr) {
std::string dataDir = cDataDir==nullptr ? "" : cDataDir; return cDataDir;
if (!dataDir.empty()) {
return dataDir;
} }
#endif
// Compute the dataDir from the user directory.
std::string dataDir;
#ifdef _WIN32 #ifdef _WIN32
cDataDir = ::getenv("USERPROFILE"); cDataDir = ::_wgetenv(L"APPDATA");
dataDir = cDataDir==nullptr ? getCurrentDirectory() : cDataDir; if (cDataDir == nullptr)
cDataDir = ::_wgetenv(L"USERPROFILE");
if (cDataDir != nullptr)
dataDir = WideToUtf8(cDataDir);
#else #else
cDataDir = ::getenv("XDG_DATA_HOME"); cDataDir = ::getenv("XDG_DATA_HOME");
dataDir = cDataDir==nullptr ? "" : cDataDir; if (cDataDir != nullptr) {
if (dataDir.empty()) { dataDir = cDataDir;
} else {
cDataDir = ::getenv("HOME"); cDataDir = ::getenv("HOME");
dataDir = cDataDir==nullptr ? getCurrentDirectory() : cDataDir; if (cDataDir != nullptr) {
dataDir = appendToDirectory(dataDir, ".local"); dataDir = cDataDir;
dataDir = appendToDirectory(dataDir, "share"); dataDir = appendToDirectory(dataDir, ".local");
dataDir = appendToDirectory(dataDir, "share");
}
} }
#endif #endif
auto ret = appendToDirectory(dataDir, "kiwix"); if (!dataDir.empty()) {
return ret; dataDir = appendToDirectory(dataDir, "kiwix");
makeDirectory(dataDir);
return dataDir;
}
// Let's use the currentDirectory
return getCurrentDirectory();
} }
static std::map<std::string, std::string> extMimeTypes = { static std::map<std::string, std::string> extMimeTypes = {