File indexing completed on 2024-12-08 13:32:53
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 "restorejob.h" 0006 0007 #include <QDir> 0008 #include <KLocalizedString> 0009 #include <utility> 0010 0011 #include <unistd.h> 0012 #include <sys/resource.h> 0013 #ifdef Q_OS_LINUX 0014 #include <sys/syscall.h> 0015 #endif 0016 0017 RestoreJob::RestoreJob(QString pRepositoryPath, QString pSourcePath, QString pRestorationPath, 0018 int pTotalDirCount, qint64 pTotalFileSize, const QHash<QString, qint64> &pFileSizes) 0019 : mRepositoryPath(std::move(pRepositoryPath)), mSourcePath(std::move(pSourcePath)), mRestorationPath(std::move(pRestorationPath)), 0020 mTotalDirCount(pTotalDirCount), mTotalFileSize(pTotalFileSize), mFileSizes(pFileSizes) 0021 { 0022 setCapabilities(Killable); 0023 mRestoreProcess.setOutputChannelMode(KProcess::SeparateChannels); 0024 int lOffset = mSourcePath.endsWith(QDir::separator()) ? -2: -1; 0025 mSourceFileName = mSourcePath.section(QDir::separator(), lOffset, lOffset); 0026 } 0027 0028 void RestoreJob::start() { 0029 setTotalAmount(Bytes, mTotalFileSize); 0030 setProcessedAmount(Bytes, 0); 0031 setTotalAmount(Files, static_cast<quint64>(mFileSizes.count())); 0032 setProcessedAmount(Files, 0); 0033 setTotalAmount(Directories, static_cast<quint64>(mTotalDirCount)); 0034 setProcessedAmount(Directories, 0); 0035 setPercent(0); 0036 mRestoreProcess << QStringLiteral("bup"); 0037 mRestoreProcess << QStringLiteral("-d") << mRepositoryPath; 0038 mRestoreProcess << QStringLiteral("restore") << QStringLiteral("-vv"); 0039 mRestoreProcess << QStringLiteral("-C") << mRestorationPath; 0040 mRestoreProcess << mSourcePath; 0041 connect(&mRestoreProcess, SIGNAL(started()), SLOT(slotRestoringStarted())); 0042 connect(&mRestoreProcess, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(slotRestoringDone(int,QProcess::ExitStatus))); 0043 mRestoreProcess.start(); 0044 mTimerId = startTimer(100); 0045 } 0046 0047 void RestoreJob::slotRestoringStarted() { 0048 makeNice(mRestoreProcess.processId()); 0049 } 0050 0051 void RestoreJob::timerEvent(QTimerEvent *pTimerEvent) { 0052 Q_UNUSED(pTimerEvent) 0053 quint64 lProcessedDirectories = processedAmount(Directories); 0054 quint64 lProcessedFiles = processedAmount(Files); 0055 quint64 lProcessedBytes = processedAmount(Bytes); 0056 bool lDirWasUpdated = false; 0057 bool lFileWasUpdated = false; 0058 QString lLastFileName; 0059 0060 while(mRestoreProcess.canReadLine()) { 0061 QString lFileName = QString::fromLocal8Bit(mRestoreProcess.readLine()).trimmed(); 0062 if(lFileName.size() == 0) { 0063 break; 0064 } 0065 if(lFileName.endsWith(QLatin1Char('/'))) { // it's a directory 0066 lProcessedDirectories++; 0067 lDirWasUpdated = true; 0068 } else { 0069 if(mSourcePath.endsWith(QDir::separator())) { 0070 lFileName.prepend(QDir::separator()); 0071 lFileName.prepend(mSourceFileName); 0072 } 0073 lProcessedBytes += mFileSizes.value(lFileName); 0074 lProcessedFiles++; 0075 lLastFileName = lFileName; 0076 lFileWasUpdated = true; 0077 } 0078 } 0079 if(lDirWasUpdated) { 0080 setProcessedAmount(Directories, lProcessedDirectories); 0081 } 0082 if(lFileWasUpdated) { 0083 emit description(this, xi18nc("progress report, current operation", "Restoring"), 0084 qMakePair(xi18nc("progress report, label", "File"), lLastFileName)); 0085 setProcessedAmount(Files, lProcessedFiles); 0086 setProcessedAmount(Bytes, lProcessedBytes); // this will also call emitPercent() 0087 } 0088 } 0089 0090 void RestoreJob::slotRestoringDone(int pExitCode, QProcess::ExitStatus pExitStatus) { 0091 killTimer(mTimerId); 0092 if(pExitStatus != QProcess::NormalExit || pExitCode != 0) { 0093 setError(1); 0094 setErrorText(QString::fromUtf8(mRestoreProcess.readAllStandardError())); 0095 } 0096 emitResult(); 0097 } 0098 0099 void RestoreJob::makeNice(int pPid) { 0100 #ifdef Q_OS_LINUX 0101 // See linux documentation Documentation/block/ioprio.txt for details of the syscall 0102 syscall(SYS_ioprio_set, 1, pPid, 3 << 13 | 7); 0103 #endif 0104 setpriority(PRIO_PROCESS, static_cast<uint>(pPid), 19); 0105 } 0106