From a68ede6f2df64ae97bf99ce556d4390a4c689b8d Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 18 Dec 2019 13:13:40 +0100 Subject: [PATCH 1/4] check_copy function --- src/libslic3r/Utils.hpp | 3 +++ src/libslic3r/utils.cpp | 23 ++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index e5fae485a..12d77c900 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -67,6 +67,9 @@ extern std::error_code rename_file(const std::string &from, const std::string &t // 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); +// Compares two files, returns 0 if identical. +extern int check_copy(const std::string& origin, const std::string& copy); + // Ignore system and hidden files, which may be created by the DropBox synchronisation process. // https://github.com/prusa3d/PrusaSlicer/issues/1298 extern bool is_plain_file(const boost::filesystem::directory_entry &path); diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 678ad9ed2..47a32b4ba 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -436,8 +436,29 @@ int copy_file(const std::string &from, const std::string &to) return -1; } boost::filesystem::permissions(target, perms, ec); + return -1; + return check_copy(from, to); +} - return 0; +int check_copy(const std::string &origin, const std::string ©) +{ + std::ifstream f1(origin, std::ifstream::binary | std::ifstream::ate); + std::ifstream f2(copy, std::ifstream::binary | std::ifstream::ate); + + if (f1.fail() || f2.fail()) { + return -1; + } + + if (f1.tellg() != f2.tellg()) { + return -1; + } + + f1.seekg(0, std::ifstream::beg); + f2.seekg(0, std::ifstream::beg); + bool ident = std::equal(std::istreambuf_iterator(f1.rdbuf()), + std::istreambuf_iterator(), + std::istreambuf_iterator(f2.rdbuf())); + return(ident ? 0 : -1); } // Ignore system and hidden files, which may be created by the DropBox synchronisation process. From ef250ad539af6c63f377742525f6da7f62700ab4 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 18 Dec 2019 14:09:16 +0100 Subject: [PATCH 2/4] copy check only if path is on removable device --- src/libslic3r/Utils.hpp | 2 +- src/libslic3r/utils.cpp | 5 ++--- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 12d77c900..5ad565ae7 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -65,7 +65,7 @@ extern std::string normalize_utf8_nfc(const char *src); extern std::error_code rename_file(const std::string &from, const std::string &to); // 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, const bool with_check = false); // Compares two files, returns 0 if identical. extern int check_copy(const std::string& origin, const std::string& copy); diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 47a32b4ba..33f85a3c2 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -417,7 +417,7 @@ std::error_code rename_file(const std::string &from, const std::string &to) #endif } -int copy_file(const std::string &from, const std::string &to) +int copy_file(const std::string &from, const std::string &to, const bool with_check) { const boost::filesystem::path source(from); const boost::filesystem::path target(to); @@ -436,8 +436,7 @@ int copy_file(const std::string &from, const std::string &to) return -1; } boost::filesystem::permissions(target, perms, ec); - return -1; - return check_copy(from, to); + return (with_check ? check_copy(from, to) : 0); } int check_copy(const std::string &origin, const std::string ©) diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index a8b88dd03..9d6a2a5ec 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -34,6 +34,7 @@ #include #include "I18N.hpp" #include "GUI.hpp" +#include "RemovableDriveManager.hpp" namespace Slic3r { @@ -107,7 +108,7 @@ void BackgroundSlicingProcess::process_fff() //FIXME localize the messages // Perform the final post-processing of the export path by applying the print statistics over the file name. std::string export_path = m_fff_print->print_statistics().finalize_output_path(m_export_path); - if (copy_file(m_temp_output_path, export_path) != 0) + if (copy_file(m_temp_output_path, export_path, GUI::RemovableDriveManager::get_instance().is_path_on_removable_drive(export_path)) != 0) throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?"))); m_print->set_status(95, _utf8(L("Running post-processing scripts"))); run_post_process_scripts(export_path, m_fff_print->config()); From 1361d21f7596b1f1c8870fd3bac5679508282589 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 18 Dec 2019 15:40:48 +0100 Subject: [PATCH 3/4] is path on removable drive --- src/slic3r/GUI/RemovableDriveManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp index 7a2464351..d9cecc3e8 100644 --- a/src/slic3r/GUI/RemovableDriveManager.cpp +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -380,9 +380,11 @@ bool RemovableDriveManager::is_path_on_removable_drive(const std::string &path) { if (m_current_drives.empty()) return false; + std::size_t found = path.find_last_of("/"); + std::string new_path = path.substr(0,found); for (auto it = m_current_drives.begin(); it != m_current_drives.end(); ++it) { - if(compare_filesystem_id(path, (*it).path)) + if(compare_filesystem_id(new_path, (*it).path)) return true; } return false; From 31b134bfccbbb1378fd65b1d86f6ec3fbcda4267 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 19 Dec 2019 15:36:00 +0100 Subject: [PATCH 4/4] copy file into .tmp and then rename if correct --- src/libslic3r/Utils.hpp | 1 + src/libslic3r/utils.cpp | 51 ++++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 5ad565ae7..c60cf6d8c 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -65,6 +65,7 @@ extern std::string normalize_utf8_nfc(const char *src); extern std::error_code rename_file(const std::string &from, const std::string &to); // Copy a file, adjust the access attributes, so that the target is writable. +int copy_file_inner(const std::string &from, const std::string &to); extern int copy_file(const std::string &from, const std::string &to, const bool with_check = false); // Compares two files, returns 0 if identical. diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 33f85a3c2..e78022053 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -417,26 +417,41 @@ std::error_code rename_file(const std::string &from, const std::string &to) #endif } +int copy_file_inner(const std::string& from, const std::string& to) +{ + const boost::filesystem::path source(from); + const boost::filesystem::path target(to); + static const auto perms = boost::filesystem::owner_read | boost::filesystem::owner_write | boost::filesystem::group_read | boost::filesystem::others_read; // aka 644 + + // Make sure the file has correct permission both before and after we copy over it. + // NOTE: error_code variants are used here to supress expception throwing. + // Error code of permission() calls is ignored on purpose - if they fail, + // the copy_file() function will fail appropriately and we don't want the permission() + // calls to cause needless failures on permissionless filesystems (ie. FATs on SD cards etc.) + // or when the target file doesn't exist. + boost::system::error_code ec; + boost::filesystem::permissions(target, perms, ec); + boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists, ec); + if (ec) { + return -1; + } + boost::filesystem::permissions(target, perms, ec); + return 0; +} + int copy_file(const std::string &from, const std::string &to, const bool with_check) { - const boost::filesystem::path source(from); - const boost::filesystem::path target(to); - static const auto perms = boost::filesystem::owner_read | boost::filesystem::owner_write | boost::filesystem::group_read | boost::filesystem::others_read; // aka 644 - - // Make sure the file has correct permission both before and after we copy over it. - // NOTE: error_code variants are used here to supress expception throwing. - // Error code of permission() calls is ignored on purpose - if they fail, - // the copy_file() function will fail appropriately and we don't want the permission() - // calls to cause needless failures on permissionless filesystems (ie. FATs on SD cards etc.) - // or when the target file doesn't exist. - boost::system::error_code ec; - boost::filesystem::permissions(target, perms, ec); - boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists, ec); - if (ec) { - return -1; - } - boost::filesystem::permissions(target, perms, ec); - return (with_check ? check_copy(from, to) : 0); + std::string to_temp = to + ".tmp"; + int ret_val = copy_file_inner(from,to_temp); + if(ret_val == 0 && with_check) + { + ret_val = check_copy(from, to_temp); + if (ret_val == 0) + { + rename_file(to_temp, to); + } + } + return ret_val; } int check_copy(const std::string &origin, const std::string ©)