2020-02-04 07:50:34 +00:00
|
|
|
#include "file_utils.h"
|
|
|
|
#include "string_utils.h"
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <dirent.h>
|
2020-06-19 13:00:29 +00:00
|
|
|
#include <limits.h>
|
2020-02-04 07:50:34 +00:00
|
|
|
#include <fstream>
|
|
|
|
#include <cstring>
|
2020-12-13 11:30:42 +00:00
|
|
|
#include <string>
|
2021-07-16 00:28:46 +00:00
|
|
|
#include <spdlog/spdlog.h>
|
2023-01-05 01:56:17 +00:00
|
|
|
#include <filesystem.h>
|
|
|
|
|
|
|
|
namespace fs = ghc::filesystem;
|
2020-02-04 07:50:34 +00:00
|
|
|
|
2023-07-25 13:27:54 +00:00
|
|
|
#ifndef PROCDIR
|
|
|
|
#define PROCDIR "/proc"
|
|
|
|
#endif
|
|
|
|
|
2020-02-04 07:50:34 +00:00
|
|
|
std::string read_line(const std::string& filename)
|
|
|
|
{
|
|
|
|
std::string line;
|
|
|
|
std::ifstream file(filename);
|
2021-12-13 13:33:39 +00:00
|
|
|
if (file.fail()){
|
|
|
|
return line;
|
|
|
|
}
|
2020-02-04 07:50:34 +00:00
|
|
|
std::getline(file, line);
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
2021-08-12 10:53:28 +00:00
|
|
|
std::string get_basename(const std::string&& path)
|
|
|
|
{
|
|
|
|
auto npos = path.find_last_of("/\\");
|
|
|
|
if (npos == std::string::npos)
|
|
|
|
return path;
|
|
|
|
|
|
|
|
if (npos < path.size() - 1)
|
|
|
|
return path.substr(npos + 1);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2021-10-01 20:34:21 +00:00
|
|
|
#ifdef __linux__
|
2020-02-04 07:50:34 +00:00
|
|
|
std::vector<std::string> ls(const char* root, const char* prefix, LS_FLAGS flags)
|
|
|
|
{
|
|
|
|
std::vector<std::string> list;
|
|
|
|
struct dirent* dp;
|
|
|
|
|
|
|
|
DIR* dirp = opendir(root);
|
|
|
|
if (!dirp) {
|
2021-07-21 16:48:45 +00:00
|
|
|
SPDLOG_ERROR("Error opening directory '{}': {}", root, strerror(errno));
|
2020-02-04 07:50:34 +00:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((dp = readdir(dirp))) {
|
2020-02-08 19:57:11 +00:00
|
|
|
if ((prefix && !starts_with(dp->d_name, prefix))
|
|
|
|
|| !strcmp(dp->d_name, ".")
|
|
|
|
|| !strcmp(dp->d_name, ".."))
|
|
|
|
continue;
|
|
|
|
|
2022-03-05 21:53:08 +00:00
|
|
|
switch (dp->d_type) {
|
|
|
|
case DT_LNK: {
|
2020-02-04 07:50:34 +00:00
|
|
|
struct stat s;
|
|
|
|
std::string path(root);
|
|
|
|
if (path.back() != '/')
|
|
|
|
path += "/";
|
|
|
|
path += dp->d_name;
|
|
|
|
|
|
|
|
if (stat(path.c_str(), &s))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (((flags & LS_DIRS) && S_ISDIR(s.st_mode))
|
2022-03-05 21:45:09 +00:00
|
|
|
|| ((flags & LS_FILES) && S_ISREG(s.st_mode))) {
|
2020-02-04 07:50:34 +00:00
|
|
|
list.push_back(dp->d_name);
|
|
|
|
}
|
2022-03-05 21:53:08 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DT_DIR:
|
|
|
|
if (flags & LS_DIRS)
|
|
|
|
list.push_back(dp->d_name);
|
|
|
|
break;
|
|
|
|
case DT_REG:
|
|
|
|
if (flags & LS_FILES)
|
|
|
|
list.push_back(dp->d_name);
|
|
|
|
break;
|
2020-02-04 07:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dirp);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool file_exists(const std::string& path)
|
|
|
|
{
|
|
|
|
struct stat s;
|
|
|
|
return !stat(path.c_str(), &s) && !S_ISDIR(s.st_mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool dir_exists(const std::string& path)
|
|
|
|
{
|
|
|
|
struct stat s;
|
|
|
|
return !stat(path.c_str(), &s) && S_ISDIR(s.st_mode);
|
|
|
|
}
|
2020-02-12 20:59:00 +00:00
|
|
|
|
2020-06-19 13:15:49 +00:00
|
|
|
std::string read_symlink(const char * link)
|
2020-02-12 20:59:00 +00:00
|
|
|
{
|
|
|
|
char result[PATH_MAX] {};
|
2020-04-10 21:30:24 +00:00
|
|
|
ssize_t count = readlink(link, result, PATH_MAX);
|
2020-02-12 20:59:00 +00:00
|
|
|
return std::string(result, (count > 0) ? count : 0);
|
|
|
|
}
|
2020-02-15 11:04:05 +00:00
|
|
|
|
2021-08-12 10:53:28 +00:00
|
|
|
std::string read_symlink(const std::string&& link)
|
|
|
|
{
|
|
|
|
return read_symlink(link.c_str());
|
|
|
|
}
|
|
|
|
|
2020-04-10 21:30:24 +00:00
|
|
|
std::string get_exe_path()
|
|
|
|
{
|
2023-07-25 13:27:54 +00:00
|
|
|
return read_symlink(PROCDIR "/self/exe");
|
2020-04-10 21:30:24 +00:00
|
|
|
}
|
|
|
|
|
2020-12-13 11:30:42 +00:00
|
|
|
std::string get_wine_exe_name(bool keep_ext)
|
2020-03-25 15:08:08 +00:00
|
|
|
{
|
2020-12-13 11:30:42 +00:00
|
|
|
const std::string exe_path = get_exe_path();
|
|
|
|
if (!ends_with(exe_path, "wine-preloader") && !ends_with(exe_path, "wine64-preloader")) {
|
|
|
|
return std::string();
|
|
|
|
}
|
|
|
|
|
2023-07-25 13:27:54 +00:00
|
|
|
std::string line = read_line(PROCDIR "/self/comm"); // max 16 characters though
|
2021-03-20 12:37:12 +00:00
|
|
|
if (ends_with(line, ".exe", true))
|
2021-03-22 19:26:11 +00:00
|
|
|
{
|
|
|
|
auto dot = keep_ext ? std::string::npos : line.find_last_of('.');
|
|
|
|
return line.substr(0, dot);
|
|
|
|
}
|
2021-03-20 12:37:12 +00:00
|
|
|
|
2023-07-25 13:27:54 +00:00
|
|
|
std::ifstream cmdline(PROCDIR "/self/cmdline");
|
2020-12-13 11:30:42 +00:00
|
|
|
// Iterate over arguments (separated by NUL byte).
|
|
|
|
while (std::getline(cmdline, line, '\0')) {
|
|
|
|
auto n = std::string::npos;
|
2020-03-25 15:08:08 +00:00
|
|
|
if (!line.empty()
|
|
|
|
&& ((n = line.find_last_of("/\\")) != std::string::npos)
|
|
|
|
&& n < line.size() - 1) // have at least one character
|
|
|
|
{
|
|
|
|
auto dot = keep_ext ? std::string::npos : line.find_last_of('.');
|
|
|
|
if (dot < n)
|
|
|
|
dot = line.size();
|
2020-12-13 11:30:42 +00:00
|
|
|
return line.substr(n + 1, dot - n - 1);
|
2020-03-25 15:08:08 +00:00
|
|
|
}
|
|
|
|
else if (ends_with(line, ".exe", true))
|
|
|
|
{
|
|
|
|
auto dot = keep_ext ? std::string::npos : line.find_last_of('.');
|
2020-12-13 11:30:42 +00:00
|
|
|
return line.substr(0, dot);
|
2020-03-25 15:08:08 +00:00
|
|
|
}
|
|
|
|
}
|
2020-12-13 11:30:42 +00:00
|
|
|
return std::string();
|
2020-03-25 15:08:08 +00:00
|
|
|
}
|
|
|
|
|
2020-02-15 11:04:05 +00:00
|
|
|
std::string get_home_dir()
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
const char* p = getenv("HOME");
|
|
|
|
|
|
|
|
if (p)
|
|
|
|
path = p;
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_data_dir()
|
|
|
|
{
|
|
|
|
const char* p = getenv("XDG_DATA_HOME");
|
|
|
|
if (p)
|
|
|
|
return p;
|
|
|
|
|
|
|
|
std::string path = get_home_dir();
|
|
|
|
if (!path.empty())
|
|
|
|
path += "/.local/share";
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_config_dir()
|
|
|
|
{
|
|
|
|
const char* p = getenv("XDG_CONFIG_HOME");
|
|
|
|
if (p)
|
|
|
|
return p;
|
|
|
|
|
|
|
|
std::string path = get_home_dir();
|
|
|
|
if (!path.empty())
|
|
|
|
path += "/.config";
|
|
|
|
return path;
|
|
|
|
}
|
2021-08-12 10:53:28 +00:00
|
|
|
|
2023-01-05 01:56:17 +00:00
|
|
|
bool lib_loaded(const std::string& lib) {
|
2023-07-25 13:27:54 +00:00
|
|
|
fs::path path(PROCDIR "/self/map_files/");
|
2023-01-05 01:56:17 +00:00
|
|
|
for (auto& p : fs::directory_iterator(path)) {
|
|
|
|
auto file = p.path().string();
|
|
|
|
auto sym = read_symlink(file.c_str());
|
|
|
|
if (sym.find(lib) != std::string::npos) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-10-01 20:34:21 +00:00
|
|
|
#endif // __linux__
|