diff --git a/src/fs_utils.cpp b/src/fs_utils.cpp index fc050fcd1..249a1e4df 100644 --- a/src/fs_utils.cpp +++ b/src/fs_utils.cpp @@ -130,9 +130,9 @@ bool fsutils::smartRemoveEmptyFolderTree(const QString& dir_path) // Remove Files created by the OS #if defined Q_WS_MAC - QFile::remove(dir_path + QLatin1String("/.DS_Store")); + fsutils::forceRemove(dir_path + QLatin1String("/.DS_Store")); #elif defined Q_WS_WIN - QFile::remove(dir_path + QLatin1String("/Thumbs.db")); + fsutils::forceRemove(dir_path + QLatin1String("/Thumbs.db")); #endif QFileInfoList sub_files = dir.entryInfoList(); @@ -151,7 +151,7 @@ bool fsutils::smartRemoveEmptyFolderTree(const QString& dir_path) } else { if (info.isHidden()) { qDebug() << Q_FUNC_INFO << "Removing hidden file: " << sub_path; - if (!QFile::remove(sub_path)) { + if (!fsutils::forceRemove(sub_path)) { qWarning() << Q_FUNC_INFO << "Failed to remove " << sub_path; return false; } @@ -164,6 +164,22 @@ bool fsutils::smartRemoveEmptyFolderTree(const QString& dir_path) return QDir().rmdir(dir_path); } +/** + * Removes the file with the given file_path. + * + * This function will try to fix the file permissions before removing it. + */ +bool fsutils::forceRemove(const QString& file_path) +{ + QFile f(file_path); + if (!f.exists()) + return true; + // Make sure we have read/write permissions + f.setPermissions(f.permissions()|QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::WriteUser); + // Remove the file + return f.remove(); +} + /** * Returns the size of a file. * If the file is a folder, it will compute its size based on its content. diff --git a/src/fs_utils.h b/src/fs_utils.h index 4c0daece0..b18149376 100644 --- a/src/fs_utils.h +++ b/src/fs_utils.h @@ -57,6 +57,7 @@ static bool sameFileNames(const QString& first, const QString& second); static QString expandPath(const QString& path); static bool isValidTorrentFile(const QString& path); static bool smartRemoveEmptyFolderTree(const QString& dir_path); +static bool forceRemove(const QString& file_path); /* Ported from Qt4 to drop dependency on QtGui */ static QString QDesktopServicesDataLocation(); diff --git a/src/geoip/geoipmanager.cpp b/src/geoip/geoipmanager.cpp index dbe6ee017..16fd491ff 100644 --- a/src/geoip/geoipmanager.cpp +++ b/src/geoip/geoipmanager.cpp @@ -101,7 +101,7 @@ void GeoIPManager::exportEmbeddedDb() { } // Remove destination files if (QFile::exists(geoipDBpath(false))) - QFile::remove(geoipDBpath(false)); + fsutils::forceRemove(geoipDBpath(false)); // Copy from executable to hard disk qDebug("%s -> %s", qPrintable(geoipDBpath(true)), qPrintable(geoipDBpath(false))); if (!QFile::copy(geoipDBpath(true), geoipDBpath(false))) { diff --git a/src/qtlibtorrent/qbtsession.cpp b/src/qtlibtorrent/qbtsession.cpp index 880acc26b..815262ba6 100644 --- a/src/qtlibtorrent/qbtsession.cpp +++ b/src/qtlibtorrent/qbtsession.cpp @@ -774,7 +774,7 @@ void QBtSession::deleteTorrent(const QString &hash, bool delete_local_files) { // Remove unneeded and incomplete files foreach (const QString &uneeded_file, uneeded_files) { qDebug("Removing uneeded file: %s", qPrintable(uneeded_file)); - QFile::remove(uneeded_file); + fsutils::forceRemove(uneeded_file); const QString parent_folder = fsutils::branchPath(uneeded_file); qDebug("Attempt to remove parent folder (if empty): %s", qPrintable(parent_folder)); QDir().rmpath(parent_folder); @@ -786,7 +786,7 @@ void QBtSession::deleteTorrent(const QString &hash, bool delete_local_files) { filters << hash+".*"; const QStringList files = torrentBackup.entryList(filters, QDir::Files, QDir::Unsorted); foreach (const QString &file, files) { - QFile::remove(torrentBackup.absoluteFilePath(file)); + fsutils::forceRemove(torrentBackup.absoluteFilePath(file)); } TorrentPersistentData::deletePersistentData(hash); // Remove tracker errors @@ -998,7 +998,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr addConsoleMessage(tr("Unable to decode torrent file: '%1'", "e.g: Unable to decode torrent file: '/home/y/xxx.torrent'").arg(from_url), QString::fromUtf8("red")); addConsoleMessage(QString::fromLocal8Bit(e.what()), "red"); //emit invalidTorrent(from_url); - QFile::remove(path); + fsutils::forceRemove(path); }else{ #if defined(Q_WS_WIN) || defined(Q_OS_OS2) QString displayed_path = path; @@ -1012,7 +1012,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red")); if (fromScanDir) { // Remove file - QFile::remove(path); + fsutils::forceRemove(path); } return h; } @@ -1044,7 +1044,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr // Delete file if temporary if (!from_url.isNull() || fromScanDir) - QFile::remove(path); + fsutils::forceRemove(path); return h; } @@ -1053,7 +1053,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr addConsoleMessage(tr("Error: The torrent %1 does not contain any file.").arg(misc::toQStringU(t->name()))); // Delete file if temporary if (!from_url.isNull() || fromScanDir) - QFile::remove(path); + fsutils::forceRemove(path); return h; } @@ -1124,7 +1124,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr if (!h.is_valid()) { qDebug("/!\\ Error: Invalid handle"); if (!from_url.isNull()) - QFile::remove(path); + fsutils::forceRemove(path); return h; } @@ -1167,7 +1167,7 @@ QTorrentHandle QBtSession::addTorrent(QString path, bool fromScanDir, QString fr // If temporary file, remove it if (!from_url.isNull() || fromScanDir) - QFile::remove(path); + fsutils::forceRemove(path); // Display console message if (!from_url.isNull()) { @@ -1469,7 +1469,7 @@ void QBtSession::loadSessionState() { if (!QFile::exists(state_path)) return; if (QFile(state_path).size() == 0) { // Remove empty invalid state file - QFile::remove(state_path); + fsutils::forceRemove(state_path); return; } QFile state_file(state_path); @@ -1641,7 +1641,7 @@ void QBtSession::saveFastResumeData() { const QString filepath = torrentBackup.absoluteFilePath(h.hash()+".fastresume"); QFile resume_file(filepath); if (resume_file.exists()) - QFile::remove(filepath); + fsutils::forceRemove(filepath); if (!out.empty() && resume_file.open(QIODevice::WriteOnly)) { resume_file.write(&out[0], out.size()); resume_file.close(); @@ -2244,7 +2244,7 @@ void QBtSession::readAlerts() { const QString filepath = torrentBackup.absoluteFilePath(h.hash()+".fastresume"); QFile resume_file(filepath); if (resume_file.exists()) - QFile::remove(filepath); + fsutils::forceRemove(filepath); qDebug("Saving fastresume data in %s", qPrintable(filepath)); vector out; bencode(back_inserter(out), *p->resume_data); diff --git a/src/rss/rssfeed.cpp b/src/rss/rssfeed.cpp index 709079f2e..459ad600c 100644 --- a/src/rss/rssfeed.cpp +++ b/src/rss/rssfeed.cpp @@ -38,6 +38,7 @@ #include "misc.h" #include "rssdownloadrulelist.h" #include "downloadthread.h" +#include "fs_utils.h" RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString &url): m_manager(manager), m_parent(parent), m_icon(":/Icons/oxygen/application-rss+xml.png"), @@ -57,7 +58,7 @@ RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString &url): RssFeed::~RssFeed() { if (!m_icon.startsWith(":/") && QFile::exists(m_icon)) - QFile::remove(m_icon); + fsutils::forceRemove(m_icon); } void RssFeed::saveItemsToDisk() { diff --git a/src/searchengine/engineselectdlg.cpp b/src/searchengine/engineselectdlg.cpp index c19662c02..56337f675 100644 --- a/src/searchengine/engineselectdlg.cpp +++ b/src/searchengine/engineselectdlg.cpp @@ -244,8 +244,8 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) { if (QFile::exists(dest_path)) { // Backup in case install fails QFile::copy(dest_path, dest_path+".bak"); - QFile::remove(dest_path); - QFile::remove(dest_path+"c"); + fsutils::forceRemove(dest_path); + fsutils::forceRemove(dest_path+"c"); update = true; } // Copy the plugin @@ -256,22 +256,22 @@ void engineSelectDlg::installPlugin(QString path, QString plugin_name) { if (!supported_engines->contains(plugin_name)) { if (update) { // Remove broken file - QFile::remove(dest_path); + fsutils::forceRemove(dest_path); // restore backup QFile::copy(dest_path+".bak", dest_path); - QFile::remove(dest_path+".bak"); + fsutils::forceRemove(dest_path+".bak"); QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be updated, keeping old version.", "%1 is the name of the search engine").arg(plugin_name)); return; } else { // Remove broken file - QFile::remove(dest_path); + fsutils::forceRemove(dest_path); QMessageBox::warning(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin could not be installed.", "%1 is the name of the search engine").arg(plugin_name)); return; } } // Install was successful, remove backup if (update) { - QFile::remove(dest_path+".bak"); + fsutils::forceRemove(dest_path+".bak"); } if (update) { QMessageBox::information(this, tr("Search plugin install")+" -- "+tr("qBittorrent"), tr("%1 search engine plugin was successfully updated.", "%1 is the name of the search engine").arg(plugin_name)); @@ -389,7 +389,7 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) { // Close file versions.close(); // Clean up tmp file - QFile::remove(versions_file); + fsutils::forceRemove(versions_file); if (file_correct && !updated) { QMessageBox::information(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("All your plugins are already up to date.")); } @@ -419,21 +419,21 @@ void engineSelectDlg::processDownloadedFile(QString url, QString filePath) { } } // Delete tmp file - QFile::remove(filePath); + fsutils::forceRemove(filePath); return; } if (url.endsWith("versions.txt")) { if (!parseVersionsFile(filePath)) { QMessageBox::warning(this, tr("Search plugin update")+" -- "+tr("qBittorrent"), tr("Sorry, update server is temporarily unavailable.")); } - QFile::remove(filePath); + fsutils::forceRemove(filePath); return; } if (url.endsWith(".py", Qt::CaseInsensitive)) { QString plugin_name = fsutils::fileName(url); plugin_name.chop(3); // Remove extension installPlugin(filePath, plugin_name); - QFile::remove(filePath); + fsutils::forceRemove(filePath); return; } } diff --git a/src/searchengine/searchengine.cpp b/src/searchengine/searchengine.cpp index d0045c69a..3965cb94e 100644 --- a/src/searchengine/searchengine.cpp +++ b/src/searchengine/searchengine.cpp @@ -468,6 +468,12 @@ void SearchEngine::downloadFinished(int exitcode, QProcess::ExitStatus) { delete downloadProcess; } +static void removePythonScriptIfExists(const QString& script_path) +{ + fsutils::forceRemove(script_path); + fsutils::forceRemove(script_path+"c"); +} + // Update nova.py search plugin if necessary void SearchEngine::updateNova() { qDebug("Updating nova"); @@ -486,53 +492,35 @@ void SearchEngine::updateNova() { // Copy search plugin files (if necessary) QString filePath = search_dir.absoluteFilePath("nova2.py"); if (getPluginVersion(":/"+nova_folder+"/nova2.py") > getPluginVersion(filePath)) { - if (QFile::exists(filePath)) { - QFile::remove(filePath); - QFile::remove(filePath+"c"); - } + removePythonScriptIfExists(filePath); QFile::copy(":/"+nova_folder+"/nova2.py", filePath); } filePath = search_dir.absoluteFilePath("nova2dl.py"); if (getPluginVersion(":/"+nova_folder+"/nova2dl.py") > getPluginVersion(filePath)) { - if (QFile::exists(filePath)) { - QFile::remove(filePath); - QFile::remove(filePath+"c"); - } + removePythonScriptIfExists(filePath); QFile::copy(":/"+nova_folder+"/nova2dl.py", filePath); } filePath = search_dir.absoluteFilePath("novaprinter.py"); if (getPluginVersion(":/"+nova_folder+"/novaprinter.py") > getPluginVersion(filePath)) { - if (QFile::exists(filePath)) { - QFile::remove(filePath); - QFile::remove(filePath+"c"); - } + removePythonScriptIfExists(filePath); QFile::copy(":/"+nova_folder+"/novaprinter.py", filePath); } filePath = search_dir.absoluteFilePath("helpers.py"); if (getPluginVersion(":/"+nova_folder+"/helpers.py") > getPluginVersion(filePath)) { - if (QFile::exists(filePath)) { - QFile::remove(filePath); - QFile::remove(filePath+"c"); - } + removePythonScriptIfExists(filePath); QFile::copy(":/"+nova_folder+"/helpers.py", filePath); } filePath = search_dir.absoluteFilePath("socks.py"); - if (QFile::exists(filePath)) { - QFile::remove(filePath); - QFile::remove(filePath+"c"); - } + removePythonScriptIfExists(filePath); QFile::copy(":/"+nova_folder+"/socks.py", filePath); if (nova_folder == "nova3") { filePath = search_dir.absoluteFilePath("sgmllib3.py"); - if (QFile::exists(filePath)) { - QFile::remove(filePath); - QFile::remove(filePath+"c"); - } + removePythonScriptIfExists(filePath); QFile::copy(":/"+nova_folder+"/sgmllib3.py", filePath); } QDir destDir(QDir(fsutils::searchEngineLocation()).absoluteFilePath("engines")); @@ -545,11 +533,7 @@ void SearchEngine::updateNova() { const QString dest_file = destDir.absoluteFilePath(file); if (getPluginVersion(shipped_file) > getPluginVersion(dest_file) ) { qDebug("shipped %s is more recent then local plugin, updating...", qPrintable(file)); - if (QFile::exists(dest_file)) { - qDebug("Removing old %s", qPrintable(dest_file)); - QFile::remove(dest_file); - QFile::remove(dest_file+"c"); - } + removePythonScriptIfExists(dest_file); qDebug("%s copied to %s", qPrintable(shipped_file), qPrintable(dest_file)); QFile::copy(shipped_file, dest_file); } diff --git a/src/torrentcreator/torrentcreatorthread.cpp b/src/torrentcreator/torrentcreatorthread.cpp index 85e378483..e1f7a0228 100644 --- a/src/torrentcreator/torrentcreatorthread.cpp +++ b/src/torrentcreator/torrentcreatorthread.cpp @@ -76,7 +76,7 @@ void TorrentCreatorThread::create(QString _input_path, QString _save_path, QStri input_path = _input_path; save_path = _save_path; if (QFile(save_path).exists()) - QFile::remove(save_path); + fsutils::forceRemove(save_path); trackers = _trackers; url_seeds = _url_seeds; comment = _comment; diff --git a/src/webui/httpconnection.cpp b/src/webui/httpconnection.cpp index 3829f6cc4..308b1cc0b 100644 --- a/src/webui/httpconnection.cpp +++ b/src/webui/httpconnection.cpp @@ -433,7 +433,7 @@ void HttpConnection::respondCommand(const QString& command) { delete tmpfile; emit torrentReadyToBeDownloaded(filePath, false, QString(), false); // Clean up - QFile::remove(filePath); + fsutils::forceRemove(filePath); } else { std::cerr << "I/O Error: Could not create temporary file" << std::endl; delete tmpfile;