On Windows, system and hidden files are now ignored in all file

enumeration loops.
Should fix "desktop.ini still displaying error" #1761
This commit is contained in:
bubnikv 2019-02-03 15:30:37 +01:00
parent 14a623f50e
commit f9743d17e9
8 changed files with 70 additions and 49 deletions

View File

@ -8,6 +8,8 @@
#include "libslic3r.h" #include "libslic3r.h"
namespace boost { namespace filesystem { class directory_entry; }}
namespace Slic3r { namespace Slic3r {
extern void set_logging_level(unsigned int level); extern void set_logging_level(unsigned int level);
@ -61,6 +63,12 @@ extern int rename_file(const std::string &from, const std::string &to);
// Copy a file, adjust the access attributes, so that the target is writable. // Copy a file, adjust the access attributes, so that the target is writable.
extern int copy_file(const std::string &from, const std::string &to); extern int copy_file(const std::string &from, const std::string &to);
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
// https://github.com/prusa3d/Slic3r/issues/1298
extern bool is_plain_file(const boost::filesystem::directory_entry &path);
extern bool is_ini_file(const boost::filesystem::directory_entry &path);
extern bool is_idx_file(const boost::filesystem::directory_entry &path);
// File path / name / extension splitting utilities, working with UTF-8, // File path / name / extension splitting utilities, working with UTF-8,
// to be published to Perl. // to be published to Perl.
namespace PerlUtils { namespace PerlUtils {

View File

@ -30,7 +30,13 @@
#include <tbb/task_scheduler_init.h> #include <tbb/task_scheduler_init.h>
#include <tbb/task_scheduler_init.h> #if defined(__linux) || defined(__GNUC__ )
#include <strings.h>
#endif /* __linux */
#ifdef _MSC_VER
#define strcasecmp _stricmp
#endif
namespace Slic3r { namespace Slic3r {
@ -248,6 +254,30 @@ int copy_file(const std::string &from, const std::string &to)
return 0; return 0;
} }
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
// https://github.com/prusa3d/Slic3r/issues/1298
bool is_plain_file(const boost::filesystem::directory_entry &dir_entry)
{
if (! boost::filesystem::is_regular_file(dir_entry.status()))
return false;
#ifdef _MSC_VER
DWORD attributes = GetFileAttributesW(boost::nowide::widen(dir_entry.path().string()).c_str());
return (attributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) == 0;
#else
return true;
#endif
}
bool is_ini_file(const boost::filesystem::directory_entry &dir_entry)
{
return is_plain_file(dir_entry) && strcasecmp(dir_entry.path().extension().string().c_str(), ".ini") == 0;
}
bool is_idx_file(const boost::filesystem::directory_entry &dir_entry)
{
return is_plain_file(dir_entry) && strcasecmp(dir_entry.path().extension().string().c_str(), ".idx") == 0;
}
} // namespace Slic3r } // namespace Slic3r
#ifdef WIN32 #ifdef WIN32

View File

@ -249,10 +249,10 @@ bool Snapshot::equal_to_active(const AppConfig &app_config) const
boost::filesystem::path path2 = snapshot_dir / subdir; boost::filesystem::path path2 = snapshot_dir / subdir;
std::vector<std::string> files1, files2; std::vector<std::string> files1, files2;
for (auto &dir_entry : boost::filesystem::directory_iterator(path1)) for (auto &dir_entry : boost::filesystem::directory_iterator(path1))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini")) if (Slic3r::is_ini_file(dir_entry))
files1.emplace_back(dir_entry.path().filename().string()); files1.emplace_back(dir_entry.path().filename().string());
for (auto &dir_entry : boost::filesystem::directory_iterator(path2)) for (auto &dir_entry : boost::filesystem::directory_iterator(path2))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini")) if (Slic3r::is_ini_file(dir_entry))
files2.emplace_back(dir_entry.path().filename().string()); files2.emplace_back(dir_entry.path().filename().string());
std::sort(files1.begin(), files1.end()); std::sort(files1.begin(), files1.end());
std::sort(files2.begin(), files2.end()); std::sort(files2.begin(), files2.end());
@ -343,7 +343,7 @@ static void copy_config_dir_single_level(const boost::filesystem::path &path_src
throw std::runtime_error(std::string("Slic3r was unable to create a directory at ") + path_dst.string()); throw std::runtime_error(std::string("Slic3r was unable to create a directory at ") + path_dst.string());
for (auto &dir_entry : boost::filesystem::directory_iterator(path_src)) for (auto &dir_entry : boost::filesystem::directory_iterator(path_src))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini")) if (Slic3r::is_ini_file(dir_entry))
boost::filesystem::copy_file(dir_entry.path(), path_dst / dir_entry.path().filename(), boost::filesystem::copy_option::overwrite_if_exists); boost::filesystem::copy_file(dir_entry.path(), path_dst / dir_entry.path().filename(), boost::filesystem::copy_option::overwrite_if_exists);
} }

View File

@ -297,7 +297,7 @@ std::vector<Index> Index::load_db()
std::vector<Index> index_db; std::vector<Index> index_db;
std::string errors_cummulative; std::string errors_cummulative;
for (auto &dir_entry : boost::filesystem::directory_iterator(cache_dir)) for (auto &dir_entry : boost::filesystem::directory_iterator(cache_dir))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".idx")) { if (Slic3r::is_idx_file(dir_entry)) {
Index idx; Index idx;
try { try {
idx.load(dir_entry.path()); idx.load(dir_entry.path());

View File

@ -635,32 +635,29 @@ void ConfigWizard::priv::load_vendors()
const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles"; const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles";
// Load vendors from the "vendors" directory in datadir // Load vendors from the "vendors" directory in datadir
for (fs::directory_iterator it(vendor_dir); it != fs::directory_iterator(); ++it) { for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir))
if (it->path().extension() == ".ini") { if (Slic3r::is_ini_file(dir_entry)) {
try { try {
auto vp = VendorProfile::from_ini(it->path()); auto vp = VendorProfile::from_ini(dir_entry.path());
vendors[vp.id] = std::move(vp); vendors[vp.id] = std::move(vp);
} }
catch (const std::exception& e) { catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % it->path() % e.what(); BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
}
} }
} }
// Additionally load up vendors from the application resources directory, but only those not seen in the datadir // Additionally load up vendors from the application resources directory, but only those not seen in the datadir
for (fs::directory_iterator it(rsrc_vendor_dir); it != fs::directory_iterator(); ++it) { for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir))
if (it->path().extension() == ".ini") { if (Slic3r::is_ini_file(dir_entry)) {
const auto id = it->path().stem().string(); const auto id = dir_entry.path().stem().string();
if (vendors.find(id) == vendors.end()) { if (vendors.find(id) == vendors.end()) {
try { try {
auto vp = VendorProfile::from_ini(it->path()); auto vp = VendorProfile::from_ini(dir_entry.path());
vendors_rsrc[vp.id] = it->path().filename().string(); vendors_rsrc[vp.id] = dir_entry.path().filename().string();
vendors[vp.id] = std::move(vp); vendors[vp.id] = std::move(vp);
} }
catch (const std::exception& e) { catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % it->path() % e.what(); BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
}
} }
} }
} }
@ -672,8 +669,9 @@ void ConfigWizard::priv::load_vendors()
} else { } else {
// In case of legacy datadir, try to guess the preference based on the printer preset files that are present // In case of legacy datadir, try to guess the preference based on the printer preset files that are present
const auto printer_dir = fs::path(Slic3r::data_dir()) / "printer"; const auto printer_dir = fs::path(Slic3r::data_dir()) / "printer";
for (fs::directory_iterator it(printer_dir); it != fs::directory_iterator(); ++it) { for (auto &dir_entry : boost::filesystem::directory_iterator(printer_dir))
auto needle = legacy_preset_map.find(it->path().filename().string()); if (Slic3r::is_ini_file(dir_entry)) {
auto needle = legacy_preset_map.find(dir_entry.path().filename().string());
if (needle == legacy_preset_map.end()) { continue; } if (needle == legacy_preset_map.end()) { continue; }
const auto &model = needle->second.first; const auto &model = needle->second.first;

View File

@ -517,16 +517,6 @@ void PresetCollection::add_default_preset(const std::vector<std::string> &keys,
++ m_num_default_presets; ++ m_num_default_presets;
} }
bool is_file_plain(const std::string &path)
{
#ifdef _MSC_VER
DWORD attributes = GetFileAttributesW(boost::nowide::widen(path).c_str());
return (attributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) == 0;
#else
return true;
#endif
}
// Load all presets found in dir_path. // Load all presets found in dir_path.
// Throws an exception on error. // Throws an exception on error.
void PresetCollection::load_presets(const std::string &dir_path, const std::string &subdir) void PresetCollection::load_presets(const std::string &dir_path, const std::string &subdir)
@ -538,10 +528,7 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
// (see the "Preset already present, not loading" message). // (see the "Preset already present, not loading" message).
std::deque<Preset> presets_loaded; std::deque<Preset> presets_loaded;
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) for (auto &dir_entry : boost::filesystem::directory_iterator(dir))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini") && if (Slic3r::is_ini_file(dir_entry)) {
// Ignore system and hidden files, which may be created by the DropBox synchronisation process.
// https://github.com/prusa3d/Slic3r/issues/1298
is_file_plain(dir_entry.path().string())) {
std::string name = dir_entry.path().filename().string(); std::string name = dir_entry.path().filename().string();
// Remove the .ini suffix. // Remove the .ini suffix.
name.erase(name.size() - 4); name.erase(name.size() - 4);

View File

@ -243,7 +243,7 @@ std::string PresetBundle::load_system_presets()
std::string errors_cummulative; std::string errors_cummulative;
bool first = true; bool first = true;
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) for (auto &dir_entry : boost::filesystem::directory_iterator(dir))
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini")) { if (Slic3r::is_ini_file(dir_entry)) {
std::string name = dir_entry.path().filename().string(); std::string name = dir_entry.path().filename().string();
// Remove the .ini suffix. // Remove the .ini suffix.
name.erase(name.size() - 4); name.erase(name.size() - 4);

View File

@ -180,11 +180,10 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
// Remove leftover paritally downloaded files, if any. // Remove leftover paritally downloaded files, if any.
void PresetUpdater::priv::prune_tmps() const void PresetUpdater::priv::prune_tmps() const
{ {
for (fs::directory_iterator it(cache_path); it != fs::directory_iterator(); ++it) { for (auto &dir_entry : boost::filesystem::directory_iterator(cache_path))
if (it->path().extension() == TMP_EXTENSION) { if (is_plain_file(dir_entry) && dir_entry.path().extension() == TMP_EXTENSION) {
BOOST_LOG_TRIVIAL(debug) << "Cache prune: " << it->path().string(); BOOST_LOG_TRIVIAL(debug) << "Cache prune: " << dir_entry.path().string();
fs::remove(it->path()); fs::remove(dir_entry.path());
}
} }
} }
@ -299,9 +298,9 @@ void PresetUpdater::priv::check_install_indices() const
{ {
BOOST_LOG_TRIVIAL(info) << "Checking if indices need to be installed from resources..."; BOOST_LOG_TRIVIAL(info) << "Checking if indices need to be installed from resources...";
for (fs::directory_iterator it(rsrc_path); it != fs::directory_iterator(); ++it) { for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_path))
const auto &path = it->path(); if (is_idx_file(dir_entry)) {
if (path.extension() == ".idx") { const auto &path = dir_entry.path();
const auto path_in_cache = cache_path / path.filename(); const auto path_in_cache = cache_path / path.filename();
if (! fs::exists(path_in_cache)) { if (! fs::exists(path_in_cache)) {
@ -319,7 +318,6 @@ void PresetUpdater::priv::check_install_indices() const
} }
} }
} }
}
// Generates a list of bundle updates that are to be performed // Generates a list of bundle updates that are to be performed
Updates PresetUpdater::priv::get_config_updates() const Updates PresetUpdater::priv::get_config_updates() const