#ifdef WITH_HYPERSCAN
#include <string>
+#include <filesystem>
#include "contrib/ankerl/unordered_dense.h"
#include "contrib/ankerl/svector.h"
#include "fmt/core.h"
cleanup_maybe();
}
- /* Have to duplicate raii_file methods to use raw filenames */
- static auto get_dir(std::string_view fname) -> std::string_view
- {
- auto sep_pos = fname.rfind(G_DIR_SEPARATOR);
-
- if (sep_pos == std::string::npos) {
- return std::string_view{fname};
- }
-
- while (sep_pos >= 1 && fname[sep_pos - 1] == G_DIR_SEPARATOR) {
- sep_pos--;
- }
-
- return std::string_view{fname.data(), sep_pos};
- }
-
- static auto get_extension(std::string_view fname) -> std::string_view
- {
- auto sep_pos = fname.rfind(G_DIR_SEPARATOR);
-
- if (sep_pos == std::string::npos) {
- sep_pos = 0;
- }
-
- auto filename = std::string_view{fname.data() + sep_pos};
- auto dot_pos = filename.find('.');
-
- if (dot_pos == std::string::npos) {
- return std::string_view{};
- }
- else {
- return std::string_view{filename.data() + dot_pos + 1, filename.size() - dot_pos - 1};
- }
- }
-
public:
hs_known_files_cache(const hs_known_files_cache &) = delete;
hs_known_files_cache(hs_known_files_cache &&) = delete;
void add_cached_file(const char *fname)
{
- auto mut_fname = std::string{fname};
- std::size_t sz;
+ auto fpath = std::filesystem::path{fname};
+ std::error_code ec;
- rspamd_normalize_path_inplace(mut_fname.data(), mut_fname.size(), &sz);
- mut_fname.resize(sz);
+ fpath = std::filesystem::canonical(fpath, ec);
- if (mut_fname.empty()) {
+ if (!ec) {
+ msg_err_hyperscan("invalid path: \"%s\", error message: %s", fname, ec.message().c_str());
+ return;
+ }
+
+ if (fpath.empty()) {
msg_err_hyperscan("attempt to add an empty hyperscan file!");
return;
}
- if (access(mut_fname.c_str(), R_OK) == -1) {
- msg_err_hyperscan("attempt to add non existing hyperscan file: %s, %s", mut_fname.c_str(),
+ if (!std::filesystem::exists(fpath)) {
+ msg_err_hyperscan("attempt to add non existing hyperscan file: %s, %s", fpath.c_str(),
strerror(errno));
return;
}
- auto dir = hs_known_files_cache::get_dir(mut_fname);
- auto ext = hs_known_files_cache::get_extension(mut_fname);
+ auto dir = fpath.parent_path();
+ auto ext = fpath.extension();
if (std::find_if(cache_dirs.begin(), cache_dirs.end(),
[&](const auto &item) { return item == dir; }) == std::end(cache_dirs)) {
- cache_dirs.emplace_back(std::string{dir});
+ cache_dirs.emplace_back(dir.string());
}
if (std::find_if(cache_extensions.begin(), cache_extensions.end(),
[&](const auto &item) { return item == ext; }) == std::end(cache_extensions)) {
- cache_extensions.emplace_back(std::string{ext});
+ cache_extensions.emplace_back(ext.string());
}
- auto is_known = known_cached_files.insert(mut_fname);
+ auto is_known = known_cached_files.insert(fpath.string());
msg_debug_hyperscan("added %s hyperscan file: %s",
is_known.second ? "new" : "already known",
- mut_fname.c_str());
+ fpath.c_str());
}
void delete_cached_file(const char *fname)
{
- auto mut_fname = std::string{fname};
- std::size_t sz;
+ auto fpath = std::filesystem::path{fname};
+ std::error_code ec;
+
+ fpath = std::filesystem::canonical(fpath, ec);
- rspamd_normalize_path_inplace(mut_fname.data(), mut_fname.size(), &sz);
- mut_fname.resize(sz);
+ if (!ec) {
+ msg_err_hyperscan("invalid path to remove: \"%s\", error message: %s",
+ fname, ec.message().c_str());
+ return;
+ }
- if (mut_fname.empty()) {
+ if (fpath.empty()) {
msg_err_hyperscan("attempt to remove an empty hyperscan file!");
return;
}
- if (access(mut_fname.c_str(), R_OK) != -1) {
- if (unlink(mut_fname.c_str()) == -1) {
- msg_err_hyperscan("cannot remove hyperscan file %s: %s",
- mut_fname.c_str(), strerror(errno));
- }
- else {
- msg_debug_hyperscan("removed hyperscan file %s", mut_fname.c_str());
- }
+ if (unlink(fpath.c_str()) == -1) {
+ msg_err_hyperscan("cannot remove hyperscan file %s: %s",
+ fpath.c_str(), strerror(errno));
}
else {
- msg_err_hyperscan("attempt to remove non-existent hyperscan file %s: %s",
- mut_fname.c_str(), strerror(errno));
+ msg_debug_hyperscan("removed hyperscan file %s", fpath.c_str());
}
- known_cached_files.erase(mut_fname);
+ known_cached_files.erase(fpath.string());
}
auto cleanup_maybe() -> void