File indexing completed on 2024-04-21 16:30:23

0001 // SPDX-FileCopyrightText: 2020 Simon Persson <simon.persson@mykolab.com>
0002 //
0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 
0005 #include "backupjob.h"
0006 #include "bupjob.h"
0007 #include "kupdaemon.h"
0008 #include "rsyncjob.h"
0009 
0010 #include <unistd.h>
0011 #include <sys/resource.h>
0012 #ifdef Q_OS_LINUX
0013 #include <sys/syscall.h>
0014 #endif
0015 
0016 #include <KLocalizedString>
0017 #include <QTimer>
0018 #include <utility>
0019 
0020 BackupJob::BackupJob(BackupPlan &pBackupPlan, QString pDestinationPath, QString pLogFilePath, KupDaemon *pKupDaemon)
0021    :mBackupPlan(pBackupPlan), mDestinationPath(std::move(pDestinationPath)), mLogFilePath(std::move(pLogFilePath)), mKupDaemon(pKupDaemon)
0022 {
0023     mLogFile.setFileName(mLogFilePath);
0024     mLogFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
0025     mLogStream.setDevice(&mLogFile);
0026 }
0027 
0028 void BackupJob::start() {
0029     mKupDaemon->registerJob(this);
0030     QStringList lRemovedPaths;
0031     for(const QString &lPath: std::as_const(mBackupPlan.mPathsIncluded)) {
0032         if(!QFile::exists(lPath)) {
0033             lRemovedPaths << lPath;
0034         }
0035     }
0036     if(!lRemovedPaths.isEmpty()) {
0037         jobFinishedError(ErrorSourcesConfig,
0038                          xi18ncp("@info notification",
0039                                  "One source folder no longer exists. Please open settings and confirm what to include in backup.<nl/>"
0040                                  "<filename>%2</filename>",
0041                                  "%1 source folders no longer exist. Please open settings and confirm what to include in backup.<nl/>"
0042                                  "<filename>%2</filename>",
0043                                  lRemovedPaths.length(), lRemovedPaths.join(QChar('\n'))));
0044         return;
0045     }
0046     QTimer::singleShot(0, this, &BackupJob::performJob);
0047 }
0048 
0049 void BackupJob::makeNice(int pPid) {
0050 #ifdef Q_OS_LINUX
0051     // See linux documentation Documentation/block/ioprio.txt for details of the syscall
0052     syscall(SYS_ioprio_set, 1, pPid, 3 << 13 | 7);
0053 #endif
0054     setpriority(PRIO_PROCESS, static_cast<uint>(pPid), 19);
0055 }
0056 
0057 QString BackupJob::quoteArgs(const QStringList &pCommand) {
0058     QString lResult;
0059     bool lFirst = true;
0060     foreach(const QString &lArg, pCommand) {
0061         if(lFirst) {
0062             lResult.append(lArg);
0063             lFirst = false;
0064         } else {
0065             lResult.append(QStringLiteral(" \""));
0066             lResult.append(lArg);
0067             lResult.append(QStringLiteral("\""));
0068         }
0069     }
0070     return lResult;
0071 }
0072 
0073 void BackupJob::jobFinishedSuccess() {
0074     // unregistring a job will normally show a UI notification that it the job was completed
0075     // setting the error code to indicate that the user canceled the job makes the UI not show
0076     // any notification. We want that since we want to trigger our own notification which has
0077     // more buttons and stuff.
0078     setError(KilledJobError);
0079     mKupDaemon->unregisterJob(this);
0080 
0081     // The error code is still used by our internal logic, for triggering our own notification.
0082     // So make sure to set it correctly.
0083     setError(NoError);
0084     emitResult();
0085 }
0086 
0087 void BackupJob::jobFinishedError(BackupJob::ErrorCodes pErrorCode, const QString &pErrorText) {
0088     // if job has already set the error that it was killed by the user then ignore any fault
0089     // we get here as that fault is surely about the process exit code was not zero.
0090     // And we don't want to report about that (with our notification) in this case.
0091     bool lWasKilled = (error() == KilledJobError);
0092 
0093     setError(KilledJobError);
0094     mKupDaemon->unregisterJob(this);
0095     if(!lWasKilled) {
0096         setError(pErrorCode);
0097         setErrorText(pErrorText);
0098     }
0099     emitResult();
0100 }
0101