query/source/core/utils/os.cpp

361 lines
6.6 KiB
C++

#include "matador/utils/os.hpp"
#include <sys/stat.h>
#include <cstring>
#include <vector>
#include <stdexcept>
#include <algorithm>
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <windows.h>
#else
#include <unistd.h>
#endif
namespace matador::utils::os {
void setenv(const char *name, const char *value, override_env_value override_value)
{
#ifdef _WIN32
_putenv_s(name, value);
#else
::setenv(name, value, static_cast<int>(override_value));
#endif
}
#ifdef _WIN32
std::string error_string(unsigned long error) {
char* lpMsgBuf;
auto bufLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
nullptr);
std::string result;
if (bufLen) {
result.append(lpMsgBuf, lpMsgBuf+bufLen);
LocalFree(lpMsgBuf);
}
return result;
}
#endif
std::string getenv(const char *name) {
#ifdef _WIN32
char var[1024];
size_t len{};
const auto error = getenv_s(&len, var, 1024, name);
if (error > 0) {
throw std::logic_error(error_string(error));
};
return var;
#else
const char *path = ::getenv(name);
return path == nullptr ? "" : path;
#endif
}
void unsetenv(const char *name)
{
#ifdef _WIN32
_putenv_s(name, nullptr);
#else
::unsetenv(name);
#endif
}
}
namespace matador::os {
FILE* fopen(const std::string &path, const char *modes)
{
return fopen(path.c_str(), modes);
}
FILE* fopen(const char *path, const char *modes)
{
#ifdef _WIN32
return _fsopen(path, modes, _SH_DENYWR);
#else
return ::fopen(path, modes);
#endif
}
FILE* freopen(const std::string &path, const char *modes, FILE *stream)
{
return os::freopen(path.c_str(), modes, stream);
}
FILE* freopen(const char *path, const char *modes, FILE *stream)
{
#ifdef _WIN32
FILE* redirected_stream;
freopen_s(&redirected_stream, path, "w+", stream);
return redirected_stream;
#else
return ::freopen(path, modes, stream);
#endif
}
bool fclose(FILE *f)
{
return ::fclose(f) == 0;
}
bool remove(const std::string &name)
{
return os::remove(name.c_str());
}
bool remove(const char *name)
{
return ::remove(name) == 0;
}
bool rename(const std::string &old_name, const std::string &new_name)
{
return os::rename(old_name.c_str(), new_name.c_str());
}
bool rename(const char *old_name, const char *new_name)
{
return ::rename(old_name, new_name) == 0;
}
bool access(const std::string &path, int mode)
{
return os::access(path.c_str(), mode);
}
bool access(const char *path, int mode)
{
#ifdef _WIN32
return _access(path, mode) == 0;
#else
return ::access(path, mode) == 0;
#endif
}
int dup(FILE *stream)
{
#ifdef _WIN32
return _dup(_fileno(stream));
#else
return ::dup(fileno(stream));
#endif
}
bool mkdir(const std::string &dirname)
{
return os::mkdir(dirname.c_str());
}
bool mkdir(const char *dirname)
{
if (dirname == nullptr || strlen(dirname) == 0) {
return true;
}
#ifdef _WIN32
return ::_mkdir(dirname) == 0;
#else
return ::mkdir(dirname, S_IRWXU) == 0;
#endif
}
bool chdir(const std::string &dirname)
{
return os::chdir(dirname.c_str());
}
bool chdir(const char *dirname)
{
if (dirname == nullptr || strlen(dirname) == 0) {
return true;
}
#ifdef _WIN32
return _chdir(dirname) == 0;
#else
return ::chdir(dirname) == 0;
#endif
}
bool rmdir(const std::string &dirname)
{
return os::rmdir(dirname.c_str());
}
bool rmdir(const char *dirname)
{
#ifdef _WIN32
return _rmdir(dirname) == 0;
#else
return ::rmdir(dirname) == 0;
#endif
}
std::string get_current_dir()
{
char buffer[1024];
#ifdef _WIN32
char *dir = _getcwd(buffer, 1024);
#else
char *dir = ::getcwd(buffer, 1024);
#endif
if (dir == nullptr) {
#ifdef _WIN32
::strerror_s(buffer, 1024, errno);
throw std::logic_error(buffer);
#else
throw std::logic_error(::strerror(errno));
#endif
}
return std::string(buffer);
}
bool mkpath(const std::string &path)
{
return os::mkpath(path.c_str());
}
#ifdef _WIN32
char DIR_SEPARATOR = '\\';
const char* DIR_SEPARATOR_STRING = "\\";
#else
char DIR_SEPARATOR = '/';
const char* DIR_SEPARATOR_STRING = "/";
#endif
bool mkpath(const char *path)
{
char tmp[256];
char *p = nullptr;
size_t len;
snprintf(tmp, sizeof(tmp),"%s",path);
len = strlen(tmp);
if (len == 0) {
return true;
}
if(tmp[len - 1] == DIR_SEPARATOR) {
tmp[len - 1] = 0;
}
for(p = tmp + 1; *p; p++) {
if (*p == DIR_SEPARATOR) {
*p = 0;
if (!os::mkdir(tmp)) {
return false;
}
*p = DIR_SEPARATOR;
}
}
return os::mkdir(tmp);
}
bool rmpath(const std::string &path)
{
return os::rmpath(path.c_str());
}
bool rmpath(const char *path)
{
// change next to last path segment
std::vector<char> pathcopy(path, path+::strlen(path)+1);
std::vector<std::string> segments;
#ifdef _WIN32
char *next_token = nullptr;
char *segment = ::strtok_s(pathcopy.data(), DIR_SEPARATOR_STRING, &next_token);
#else
char *segment = ::strtok(pathcopy.data(), DIR_SEPARATOR_STRING);
#endif
while (segment != nullptr) {
os::chdir(segment);
segments.emplace_back(segment);
#ifdef _WIN32
segment = ::strtok_s(nullptr, DIR_SEPARATOR_STRING, &next_token);
#else
segment = ::strtok(nullptr, DIR_SEPARATOR_STRING);
#endif
}
auto first = segments.rbegin();
for (auto it=first; it!=segments.rend(); ++it) {
os::chdir("..");
os::rmdir(*it);
}
return true;
}
bool is_readable(const std::string &path)
{
return is_readable(path.c_str());
}
bool is_readable(const char *path)
{
return os::access(path, 2);
}
bool is_writable(const std::string &path)
{
return is_writable(path.c_str());
}
bool is_writable(const char *path)
{
return os::access(path, 4);
}
bool exists(const std::string &path)
{
return exists(path.c_str());
}
bool exists(const char *path)
{
return os::access(path, 0);
}
size_t file_size(FILE *stream)
{
#ifdef _WIN32
int fd = _fileno(stream);
return ::_filelength(fd);
#else
int fd = ::fileno(stream);
struct stat buf{};
::fstat(fd, &buf);
return buf.st_size;
#endif
}
std::string build_path(const std::string &a, const std::string &b)
{
return a + DIR_SEPARATOR_STRING + b;
}
char* strerror(int err, char* errbuf, size_t bufsize)
{
#ifdef _WIN32
::strerror_s(errbuf, bufsize, err);
return errbuf;
#else
auto msg = ::strerror(err);
auto s = strlen(msg);
if (s < bufsize - 1) {
return strcpy(errbuf, msg);
} else {
errbuf[bufsize - 1] = '\0';
return strncpy(errbuf, msg, bufsize - 1);
}
#endif
}
}