diff --git a/backup-daemon/backup-daemon.pro b/backup-daemon/backup-daemon.pro old mode 100644 new mode 100755 index c290d8b..fd9bcc5 --- a/backup-daemon/backup-daemon.pro +++ b/backup-daemon/backup-daemon.pro @@ -31,6 +31,7 @@ HEADERS += \ mymountproxy.h \ myprocess/calcbackupsize.h \ myprocess/mountbackupprocess.h \ + myprocess/rsyncpathtodirprocess.h \ parsebackuplist.h \ systembackupproxy.h \ workerfactory.h @@ -47,6 +48,7 @@ SOURCES += \ mymountproxy.cpp \ myprocess/calcbackupsize.cpp \ myprocess/mountbackupprocess.cpp \ + myprocess/rsyncpathtodirprocess.cpp \ parsebackuplist.cpp \ systembackupproxy.cpp \ workerfactory.cpp diff --git a/backup-daemon/backupmanager_adaptor.cpp b/backup-daemon/backupmanager_adaptor.cpp old mode 100644 new mode 100755 index 878a730..34cf0c1 --- a/backup-daemon/backupmanager_adaptor.cpp +++ b/backup-daemon/backupmanager_adaptor.cpp @@ -105,11 +105,11 @@ int ManagerAdaptor::goRestore(BackupWrapper backupWrapper) return out0; } -int ManagerAdaptor::cancel() +int ManagerAdaptor::cancel(BackupWrapper backupWrapper) { // handle method call com.kylin.backup.manager.goRestore int out0; - QMetaObject::invokeMethod(parent(), "cancel", Q_RETURN_ARG(int, out0)); + QMetaObject::invokeMethod(parent(), "cancel", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper)); return out0; } diff --git a/backup-daemon/backupmanager_adaptor.h b/backup-daemon/backupmanager_adaptor.h old mode 100644 new mode 100755 index c50475d..ad82080 --- a/backup-daemon/backupmanager_adaptor.h +++ b/backup-daemon/backupmanager_adaptor.h @@ -100,6 +100,8 @@ class ManagerAdaptor: public QDBusAbstractAdaptor " \n" " \n" " \n" +" \n" +" \n" " \n" " \n" "") @@ -118,7 +120,7 @@ public Q_SLOTS: // METHODS int ghostBackup(BackupWrapper backupWrapper); int goBackup(BackupWrapper backupWrapper); int goRestore(BackupWrapper backupWrapper); - int cancel(); + int cancel(BackupWrapper backupWrapper); Q_SIGNALS: // SIGNALS void sendBackupResult(bool result); void sendDeleteResult(bool result); diff --git a/backup-daemon/com.kylin.backup.manager.xml b/backup-daemon/com.kylin.backup.manager.xml old mode 100644 new mode 100755 diff --git a/backup-daemon/main.cpp b/backup-daemon/main.cpp old mode 100644 new mode 100755 index a04a5b6..a482667 --- a/backup-daemon/main.cpp +++ b/backup-daemon/main.cpp @@ -30,6 +30,7 @@ int main(int argc, char *argv[]) qDebug() << QString("测试 begin"); BackupWrapper backupWrapper; + backupWrapper.m_backupExcludePaths = Utils::getFromExcludePathsFile(); MyBackupManager manager; manager.checkEnv(backupWrapper); diff --git a/backup-daemon/mybackupmanager.cpp b/backup-daemon/mybackupmanager.cpp old mode 100644 new mode 100755 index 1e4d0de..0f86d20 --- a/backup-daemon/mybackupmanager.cpp +++ b/backup-daemon/mybackupmanager.cpp @@ -41,7 +41,7 @@ int MyBackupManager::Mount_backup_partition() /** * @brief 环境检测 * @param backupWrapper,参数 - * @return + * @return 0,正确启动;非0,出现错误 */ int MyBackupManager::checkEnv(const BackupWrapper& backupWrapper) { @@ -57,8 +57,10 @@ int MyBackupManager::checkEnv(const BackupWrapper& backupWrapper) } worker->setParam(backupWrapper); - connect(worker, &Worker::checkResult, this, &MyBackupManager::sendEnvCheckResult); - connect(worker, &Worker::checkResult, this, &MyBackupManager::finished); + connect(worker, &Worker::checkResult, this, [&] (int result) { + emit this->sendEnvCheckResult(result); + this->finished(); + }); worker->moveToThread(&workerThread); connect(&workerThread, &QThread::started, worker, &Worker::checkEnv); connect(&workerThread, &QThread::finished, worker, &Worker::deleteLater); @@ -71,12 +73,39 @@ int MyBackupManager::checkEnv(const BackupWrapper& backupWrapper) /** * @brief 备份 * @param backupWrapper - * @return + * @return 0,正确启动备份;非0,出现错误 */ int MyBackupManager::goBackup(const BackupWrapper& backupWrapper) { - Q_UNUSED(backupWrapper) - return 0; + if (m_isActive || !lock(backupWrapper.m_frontUid)) { + emit sendEnvCheckResult(int(BackupResult::LOCK_PROGRAM_FAIL)); + return int(BackupResult::LOCK_PROGRAM_FAIL); + } + + Worker* worker = WorkerFactory::createWorker(backupWrapper.m_type, backupWrapper.m_iPosition); + if (nullptr == worker) { + emit sendEnvCheckResult(int(BackupResult::NO_FOUND_DEALCLASS)); + return int(BackupResult::NO_FOUND_DEALCLASS); + } + + worker->setParam(backupWrapper); + connect(worker, &Worker::checkResult, this, [&](int result) { + emit this->sendEnvCheckResult(result); + if (result != int(BackupResult::CHECK_ENV_SUCCESS)) { + this->finished(); + } + }); + connect(worker, &Worker::workResult, this, [&] (bool result) { + emit this->sendBackupResult(result); + this->finished(); + }); + worker->moveToThread(&workerThread); + connect(&workerThread, &QThread::started, worker, &Worker::doWork); + connect(&workerThread, &QThread::finished, worker, &Worker::deleteLater); + + workerThread.start(); + + return int(BackupResult::BACKUP_RESULT_INIT); } /** @@ -156,7 +185,7 @@ int MyBackupManager::getBackupState(bool& isActive) /** * @brief 取消操作 */ -int MyBackupManager::cancel() +int MyBackupManager::cancel(const BackupWrapper& backupWrapper) { return 0; } diff --git a/backup-daemon/mybackupmanager.h b/backup-daemon/mybackupmanager.h old mode 100644 new mode 100755 index b2f0bb4..c65b4f0 --- a/backup-daemon/mybackupmanager.h +++ b/backup-daemon/mybackupmanager.h @@ -52,7 +52,7 @@ public slots: // 获取备份状态 int getBackupState(bool& isActive); // 取消操作 - int cancel(); + int cancel(const BackupWrapper& backupWrapper); // 任务结束 void finished(); diff --git a/backup-daemon/mymountproxy.cpp b/backup-daemon/mymountproxy.cpp old mode 100644 new mode 100755 diff --git a/backup-daemon/mymountproxy.h b/backup-daemon/mymountproxy.h old mode 100644 new mode 100755 diff --git a/backup-daemon/myprocess/calcbackupsize.cpp b/backup-daemon/myprocess/calcbackupsize.cpp old mode 100644 new mode 100755 index 4083365..45a965b --- a/backup-daemon/myprocess/calcbackupsize.cpp +++ b/backup-daemon/myprocess/calcbackupsize.cpp @@ -5,6 +5,10 @@ CalcBackupSize::CalcBackupSize(QObject* parent) : QObject(parent), m_process(new QProcess(this)) { + connect(m_process, &QProcess::readyRead, this, [&]() { + parseResult(); + }); + connect(m_process, &QProcess::readyReadStandardError, this, [&]() { QByteArray err = m_process->readAllStandardError(); qCritical("backup process error: %s", err.data()); @@ -14,12 +18,14 @@ CalcBackupSize::CalcBackupSize(QObject* parent) : m_process->kill(); }); - connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(getCalcResult(int, QProcess::ExitStatus))); + connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinish(int, QProcess::ExitStatus))); } CalcBackupSize::~CalcBackupSize() { - + if (!m_process && m_process->state() != QProcess::NotRunning) { + m_process->kill(); + } } /** @@ -28,8 +34,10 @@ CalcBackupSize::~CalcBackupSize() * @param block 是否阻塞计算模式。默认true——阻塞计算模式 * @return block为true时返回值为待备份数据大小,单位字节;block为false时,默认返回0; */ -qint64 CalcBackupSize::calcBackupSize(QStringList args, bool block) +qint64 CalcBackupSize::start(QStringList args, bool block) { + qDebug() << "CalcBackupSize::calcBackupSize invoke begin"; + QString cmd("rsync "); for (const QString& item : args) { cmd += " "; @@ -49,53 +57,66 @@ qint64 CalcBackupSize::calcBackupSize(QStringList args, bool block) m_process->waitForFinished(); } + qDebug() << "CalcBackupSize::calcBackupSize invoke end"; return m_size; } /** - * @brief 解析结果 - * @param exitCode + * @brief 解析process的输出结果 */ -void CalcBackupSize::getCalcResult(int exitCode, QProcess::ExitStatus) +void CalcBackupSize::parseResult() { // 解析结果,结果内容样例如下: /* - Number of files: 8 (reg: 4, dir: 4) - Number of created files: 7 (reg: 4, dir: 3) + Number of files: 256,274 (reg: 207,101, dir: 23,764, link: 25,407, special: 2) + Number of created files: 256,274 (reg: 207,101, dir: 23,764, link: 25,407, special: 2) Number of deleted files: 0 - Number of regular files transferred: 4 - Total file size: 20 bytes - Total transferred file size: 20 bytes + Number of regular files transferred: 207,101 + Total file size: 12,160,363,663 bytes + Total transferred file size: 12,159,780,794 bytes Literal data: 0 bytes Matched data: 0 bytes - File list size: 0 + File list size: 786,254 File list generation time: 0.001 seconds File list transfer time: 0.000 seconds - Total bytes sent: 248 - Total bytes received: 43 + Total bytes sent: 8,273,515 + Total bytes received: 794,093 + + sent 8,273,515 bytes received 794,093 bytes 1,209,014.40 bytes/sec + total size is 12,160,363,663 speedup is 1,341.08 (DRY RUN) - sent 248 bytes received 43 bytes 582.00 bytes/sec - total size is 20 speedup is 0.07 (DRY RUN) */ QString out(m_process->readAll()); QStringList lines = out.split("\n"); for (QString& line : lines) { line.trimmed(); // 获取文件夹数目 - if (line.startsWith("Number of files:")) { - int indexOfLastColon = line.lastIndexOf(":"); - int indexOfLastLable = line.lastIndexOf(")"); - int numOfDirs = line.mid(indexOfLastColon+1, indexOfLastLable-indexOfLastColon).trimmed().toInt(); - // 每个目录下还都有.和..,故总数还要*3 - numOfDirs *= 3; - // ext4格式的目录本身要占用4K空间(4096) - m_size += numOfDirs * 4096; - } - if (line.startsWith("Total file size:")) { - m_size += line.replace("Total file size:", "").replace("bytes", "").trimmed().toLongLong(); - break ; +// if (line.startsWith("Number of files:")) { +// int indexOfDir = line.indexOf("dir: "); +// indexOfDir += 5; +// int indexOfDirEnd = line.indexOf(QRegularExpression("[ )]"), indexOfDir); +// int numOfDirs = line.mid(indexOfDir, indexOfDirEnd-indexOfDir).replace(",","").trimmed().toInt(); +// // 每个目录下还都有.和..,故总数还要*3 +// numOfDirs *= 3; +// // ext4格式的目录本身要占用4K空间(4096) +// m_size += numOfDirs * 4096; +// } + if (line.startsWith("Total transferred file size: ")) { + m_size += line.replace("Total file size:", "").replace("bytes", "").replace(",","").trimmed().toLongLong(); } } - - emit calcFinished(m_size); +} + +/** + * @brief process结束 + * @param exitCode + */ +void CalcBackupSize::processFinish(int exitCode, QProcess::ExitStatus) +{ + qDebug() << "CalcBackupSize::getCalcResult invoke begin"; + + parseResult(); + emit finished(m_size); + + qDebug() << "CalcBackupSize::getCalcResult invoke end"; } diff --git a/backup-daemon/myprocess/calcbackupsize.h b/backup-daemon/myprocess/calcbackupsize.h old mode 100644 new mode 100755 index 1850679..6cc4695 --- a/backup-daemon/myprocess/calcbackupsize.h +++ b/backup-daemon/myprocess/calcbackupsize.h @@ -21,15 +21,22 @@ public: * @param block 是否阻塞计算模式。默认true——阻塞计算模式 * @return block为true时返回值为待备份数据大小,单位字节;block为false时,默认返回0 */ - qint64 calcBackupSize(QStringList args, bool block = true); + qint64 start(QStringList args, bool block = true); signals: - void calcFinished(qint64 size); + // 计算结束信号 + void finished(qint64 size); private slots: - void getCalcResult(int exitCode, QProcess::ExitStatus); + // process结束槽 + void processFinish(int exitCode, QProcess::ExitStatus); private: + /** + * @brief 解析process的输出结果 + */ + void parseResult(); + QProcess * m_process; qint64 m_size = 0; // 备份大小,单位字节 diff --git a/backup-daemon/myprocess/mountbackupprocess.cpp b/backup-daemon/myprocess/mountbackupprocess.cpp old mode 100644 new mode 100755 diff --git a/backup-daemon/myprocess/mountbackupprocess.h b/backup-daemon/myprocess/mountbackupprocess.h old mode 100644 new mode 100755 diff --git a/backup-daemon/myprocess/rsyncpathtodirprocess.cpp b/backup-daemon/myprocess/rsyncpathtodirprocess.cpp new file mode 100755 index 0000000..c11baa3 --- /dev/null +++ b/backup-daemon/myprocess/rsyncpathtodirprocess.cpp @@ -0,0 +1,88 @@ +#include "rsyncpathtodirprocess.h" +#include +#include + +RsyncPathToDirProcess::RsyncPathToDirProcess(QObject *parent) : + QObject(parent), + m_p(new QProcess(this)) +{ + m_currentRate = 0; + m_bSuccess = false; + + connect(m_p, &QProcess::readyRead, this, [&]() { + QString str = QString(m_p->readAll()); + if (str.contains("B\/s") && str.contains("%")) { + if (str.split("%").at(0).length() < 3) + return; + int tmpRate = str.split("%").at(0).right(3).toInt(); + if (m_currentRate == tmpRate) + return; + m_currentRate = tmpRate; + sync(); + emit progress(m_currentRate); + } + }); + + connect(m_p, &QProcess::readyReadStandardError, this, [&]() { + QByteArray err = m_p->readAllStandardError(); + qCritical("backup process error: %s", err.data()); + }); + + connect(m_p, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) { + m_p->kill(); + }); + + connect(m_p, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus))); +} + +RsyncPathToDirProcess::~RsyncPathToDirProcess() +{ + if (!m_p && m_p->state() != QProcess::NotRunning) { + m_p->kill(); + } +} + +bool RsyncPathToDirProcess::start(QStringList args, bool block) +{ + qDebug() << "RsyncPathToDirProcess::start invoke begin"; + m_currentRate = 0; + m_bSuccess = false; + + QString cmd("rsync "); + for (const QString& item : args) { + cmd += " "; + cmd += item; + } + qDebug() << cmd; + + m_p->start("rsync", args); + if (!m_p->waitForStarted()) { + qCritical("rsync started failed"); + return false; + } + + if (block) { + if (!m_p->waitForFinished()) { + qCritical("rsync finished failed"); + return false; + } + } + + qDebug() << "RsyncPathToDirProcess::start invoke end"; + return m_bSuccess; +} + +void RsyncPathToDirProcess::processFinished(int exitCode, QProcess::ExitStatus) +{ + qDebug() << "RsyncPathToDirProcess::processFinished invoke begin"; + + if (exitCode == QProcess::NormalExit || exitCode == 24 || exitCode == 23) { + sync(); + m_bSuccess = true; + emit finished(true); + } else { + emit finished(false); + } + + qDebug() << "RsyncPathToDirProcess::processFinished invoke end"; +} diff --git a/backup-daemon/myprocess/rsyncpathtodirprocess.h b/backup-daemon/myprocess/rsyncpathtodirprocess.h new file mode 100755 index 0000000..b69715c --- /dev/null +++ b/backup-daemon/myprocess/rsyncpathtodirprocess.h @@ -0,0 +1,31 @@ +#ifndef RSYNCPATHTODIRPROCESS_H +#define RSYNCPATHTODIRPROCESS_H + +#include + +class RsyncPathToDirProcess : public QObject +{ + Q_OBJECT +public: + RsyncPathToDirProcess(QObject *parent = nullptr); + ~RsyncPathToDirProcess(); + + bool start(QStringList args, bool block = true); + +signals: + // 结果信号 + void finished(bool result); + // 进度百分比 + void progress(int currentRate); + +private slots: + // m_p执行结束 + void processFinished(int exitCode, QProcess::ExitStatus); + +private: + QProcess * m_p; + int m_currentRate; + bool m_bSuccess; +}; + +#endif // RSYNCPATHTODIRPROCESS_H diff --git a/backup-daemon/parsebackuplist.cpp b/backup-daemon/parsebackuplist.cpp old mode 100644 new mode 100755 diff --git a/backup-daemon/parsebackuplist.h b/backup-daemon/parsebackuplist.h old mode 100644 new mode 100755 diff --git a/backup-daemon/systembackupproxy.cpp b/backup-daemon/systembackupproxy.cpp old mode 100644 new mode 100755 index 93033bb..561d6a8 --- a/backup-daemon/systembackupproxy.cpp +++ b/backup-daemon/systembackupproxy.cpp @@ -10,15 +10,21 @@ IMPLEMENT_DYNCREATE(SystemBackupProxy) SystemBackupProxy::SystemBackupProxy() -{} +{ + m_bSuccess = false; + m_p = nullptr; +} SystemBackupProxy::~SystemBackupProxy() -{} +{ + delete m_p; +} /** * @brief 环境检测 + * @return false,检测失败;true,检测成功 */ -void SystemBackupProxy::checkEnvEx() +bool SystemBackupProxy::checkEnvEx() { qDebug() << "SystemBackupProxy::checkEnv invoke begin"; @@ -26,29 +32,40 @@ void SystemBackupProxy::checkEnvEx() MyMountProxy mountProxy; if ( MyMountProxy::MountResult::MOUNTED != mountProxy.mountBackupPartition() ) { emit checkResult(int(BackupResult::BACKUP_PARTITION_MOUNT_FAIL)); - return ; + return false; } - // 2、检测备份是否增量备份 - checkIsIncBackup(); + // 2、判断备份是否增量备份 + isIncBackup(); // 3、检测空间是否满足备份 - checkFreeCapacity(); + bool result = checkFreeCapacity(); qDebug() << "SystemBackupProxy::checkEnv invoke end"; + return result; } +/** + * @brief 执行备份逻辑 + */ void SystemBackupProxy::doWorkEx() -{} +{ + // 环境检测 + if (!checkEnvEx()) + return ; + + // 开始备份 + doBackup(); +} void SystemBackupProxy::cancelEx() {} /** - * @brief 校验是否增量备份 + * @brief 判断是否增量备份 * @return true,增量备份; false,全量备份 */ -bool SystemBackupProxy::checkIsIncBackup() +bool SystemBackupProxy::isIncBackup() { QString backupPath; ParseBackupList::BackupPoint point; @@ -76,8 +93,10 @@ bool SystemBackupProxy::checkIsIncBackup() /** * @brief 校验剩余空间是否满足备份 */ -void SystemBackupProxy::checkFreeCapacity() +bool SystemBackupProxy::checkFreeCapacity() { + qDebug() << "SystemBackupProxy::checkFreeCapacity invoke begin"; + // 1、计算待备份数据的大小 qint64 itotalSize = calcSizeForBackup(); // 备份过程中会有一些临时文件产生,会占用一部分空间,故我们预留500M的空间 @@ -90,10 +109,16 @@ void SystemBackupProxy::checkFreeCapacity() qint64 freeSize = backupDisk.bytesFree(); // 3、校验空间是否足够 + bool result = true; if (itotalSize > freeSize) { emit checkResult(int(BackupResult::BACKUP_CAPACITY_IS_NOT_ENOUGH)); - return ; + result = false; + } else { + emit checkResult(int(BackupResult::CHECK_ENV_SUCCESS)); } + + qDebug() << "SystemBackupProxy::checkFreeCapacity invoke end"; + return result; } /** @@ -102,18 +127,26 @@ void SystemBackupProxy::checkFreeCapacity() */ qint64 SystemBackupProxy::calcSizeForBackup() { + QString destPath = Utils::getSysRootPath(); + QStringList args; if (m_backupWrapper.m_bIncrement) { if (m_backupWrapper.m_uuid.isEmpty()) { // 新增增量备份点场景 args = getRsyncArgs(SystemBackupScene::TRY_INC_SYSTEM_BACKUP); + destPath += CHECK_PATH; } else { // 在原来的备份点上增量备份场景 args = getRsyncArgs(SystemBackupScene::TRY_INC_SYSTEM_BACKUP_AT_BASE); + destPath += BACKUP_SNAPSHOTS_PATH; + destPath += "/"; + destPath += m_backupWrapper.m_uuid; + destPath += "/data/"; } } else { // 全量备份场景 args = getRsyncArgs(SystemBackupScene::TRY_SYSTEM_BACKUP); + destPath += CHECK_PATH; } // 拼接备份源路径和目标路径 @@ -121,14 +154,12 @@ qint64 SystemBackupProxy::calcSizeForBackup() srcPath += "/"; srcPath.replace("//", "/"); args << srcPath; - QString destPath = Utils::getSysRootPath(); - destPath += CHECK_PATH; destPath.replace("//", "/"); args << destPath; Utils::mkpath(destPath); CalcBackupSize calcator; - return calcator.calcBackupSize(args); + return calcator.start(args); } /** @@ -150,7 +181,7 @@ QStringList SystemBackupProxy::getRsyncArgs(SystemBackupScene scene) args << "-avAXr"; args << "--progress"; args << "--ignore-missing-args"; - args << QString("--link-dest=../%1/data").arg(m_baseUuid); + args << QString("--link-dest=../../%1/data").arg(m_backupWrapper.m_baseUuid); break ; case SystemBackupScene::INC_SYSTEM_BACKUP_AT_BASE : args << "-avAXr"; @@ -167,7 +198,7 @@ QStringList SystemBackupProxy::getRsyncArgs(SystemBackupScene scene) args << "-aAXrn"; args << "--stats"; args << "--ignore-missing-args"; - args << QString("--link-dest=../%1/data").arg(m_baseUuid); + args << QString("--link-dest=../../%1/data").arg(m_backupWrapper.m_baseUuid); break ; case SystemBackupScene::TRY_INC_SYSTEM_BACKUP_AT_BASE : args << "-aAXrn"; @@ -175,15 +206,121 @@ QStringList SystemBackupProxy::getRsyncArgs(SystemBackupScene scene) args << "--ignore-missing-args"; args << "--delete"; break ; + case SystemBackupScene::EFI_BACKUP : + args << "-avAXr"; + args << "--progress"; + args << "--ignore-missing-args"; + break ; default: return args; } - // --exclude=排除路径设置 - for (const QString & item : m_backupWrapper.m_backupExcludePaths) { - args << QString("--exclude=%1").arg(item); + if (SystemBackupScene::EFI_BACKUP != scene) { + // --exclude=排除路径设置 + for (const QString & item : m_backupWrapper.m_backupExcludePaths) { + args << QString("--exclude=%1").arg(item); + } } return args; } +/** + * @brief 备份 + */ +void SystemBackupProxy::doBackup() +{ + qDebug() << "SystemBackupProxy::doBackup invoke begin"; + + // 准备 + if (!doPrepare()) + return ; + + // 启动备份efi + if (!backupEfi()) { + emit checkResult(int(BackupResult::EFI_RSYNC_FAIL)); + return ; + } + + // 启动系统备份 + + qDebug() << "SystemBackupProxy::doBackup invoke end"; +} + +/** + * @brief 备份准备 + * @return true,准备成功;false,准备失败 + */ +bool SystemBackupProxy::doPrepare() +{ + qDebug() << "SystemBackupProxy::doPrepare invoke begin"; + + // 1、设置当前备份的Uuid + if (m_backupWrapper.m_uuid.isEmpty()) { + // 新增备份点,不指定uuid的场景 + m_curUuid = "{"; + m_curUuid += Utils::createUuid(); + m_curUuid += "}"; + } else { + // 指定uuid备份的场景 + m_curUuid = m_backupWrapper.m_uuid; + } + + // 2、准备备份目录及文件 + m_destPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/data"; + m_destPath.replace("//", "/"); + if (!Utils::mkpath(m_destPath)) { + emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED)); + qCritical() << QString("mkdir %1 failed !").arg(m_destPath) ; + return false; + } + + QString userFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + PATHS_USER_FILE; + userFile.replace("//", "/"); + if (Utils::writeFileByLines(userFile, m_backupWrapper.m_backupPaths)) { + emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED)); + qCritical() << QString("create file %1 failed !").arg(userFile) ; + return false; + } + + QString excludeUserFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + EXCLUDE_PATHS_USER_FILE; + excludeUserFile.replace("//", "/"); + if (Utils::writeFileByLines(userFile, m_backupWrapper.m_backupPaths)) { + emit checkResult(int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED)); + qCritical() << QString("create file %1 failed !").arg(excludeUserFile) ; + return false; + } + + qDebug() << "SystemBackupProxy::doPrepare invoke end"; + return true; +} + +/** + * @brief 备份/boot/efi + * @return true,备份成功;false,备份失败 + */ +bool SystemBackupProxy::backupEfi() +{ + qDebug() << "SystemBackupProxy::backupEfi invoke begin"; + + // /boot/efi分区是自动挂载的,这里不用去挂载 + QString efiPath = Utils::getSysRootPath() + "/boot/efi"; + efiPath.replace("//", "/"); + + QStringList args; + if (Utils::isDirExist(efiPath)) { + args = getRsyncArgs(SystemBackupScene::EFI_BACKUP); + } + + args << efiPath; + args << m_destPath; + + m_p = new RsyncPathToDirProcess(this); + bool result = m_p->start(args); + delete m_p; + m_p = nullptr; + + qDebug() << "SystemBackupProxy::backupEfi invoke end"; + return result; +} + diff --git a/backup-daemon/systembackupproxy.h b/backup-daemon/systembackupproxy.h old mode 100644 new mode 100755 index 540c385..480733a --- a/backup-daemon/systembackupproxy.h +++ b/backup-daemon/systembackupproxy.h @@ -2,6 +2,7 @@ #define SYSTEMBACKUPPROXY_H #include "workerfactory.h" +#include "myprocess/rsyncpathtodirprocess.h" class SystemBackupProxy : public Worker { @@ -16,6 +17,7 @@ public: TRY_SYSTEM_BACKUP, // 测试系统备份,可用于计算备份传输数据大小 TRY_INC_SYSTEM_BACKUP, // 测试增量系统备份,可用于计算备份传输数据大小 TRY_INC_SYSTEM_BACKUP_AT_BASE, // 测试增量系统备份,在原备份点里增量备份,可用于计算备份传输数据大小 + EFI_BACKUP, // 备份/boot/efi }; explicit SystemBackupProxy(); @@ -23,7 +25,7 @@ public: public: // 环境检测 - virtual void checkEnvEx(); + virtual bool checkEnvEx(); // 任务处理 virtual void doWorkEx(); @@ -32,11 +34,11 @@ public: virtual void cancelEx(); private: - // 校验是否增量备份 - bool checkIsIncBackup(); + // 判断是否增量备份 + bool isIncBackup(); // 校验剩余空间是否满足备份 - void checkFreeCapacity(); + bool checkFreeCapacity(); // 计算备份所需空间大小 qint64 calcSizeForBackup(); @@ -48,10 +50,24 @@ private: */ QStringList getRsyncArgs(SystemBackupScene scene); - // 是否增量备份 - bool m_bIncrement = false; - // 基准备份点,新增增量备份点时用 - QString m_baseUuid; + // 备份准备 + bool doPrepare(); + + // 备份 + void doBackup(); + + // 备份/boot/efi + bool backupEfi(); + + // 是否备份成功 + bool m_bSuccess; + // 当前备份uuid + QString m_curUuid; + // 当前备份目标目录 + QString m_destPath; + // 备份进程 + RsyncPathToDirProcess *m_p; + }; #endif // SYSTEMBACKUPPROXY_H diff --git a/backup-daemon/workerfactory.cpp b/backup-daemon/workerfactory.cpp old mode 100644 new mode 100755 index adddd60..4842ab9 --- a/backup-daemon/workerfactory.cpp +++ b/backup-daemon/workerfactory.cpp @@ -34,7 +34,7 @@ void Worker::cancel() } // 环境检测,个性化部分派生类去实现 -void Worker::checkEnvEx() +bool Worker::checkEnvEx() {} // 任务处理,个性化部分派生类去实现 diff --git a/backup-daemon/workerfactory.h b/backup-daemon/workerfactory.h old mode 100644 new mode 100755 index 48468b7..8a1da39 --- a/backup-daemon/workerfactory.h +++ b/backup-daemon/workerfactory.h @@ -33,7 +33,7 @@ public slots: protected: // 环境检测,个性化部分派生类去实现 - virtual void checkEnvEx(); + virtual bool checkEnvEx(); // 任务处理,个性化部分派生类去实现 virtual void doWorkEx(); diff --git a/common/mydefine.cpp b/common/mydefine.cpp old mode 100644 new mode 100755 diff --git a/common/mydefine.h b/common/mydefine.h old mode 100644 new mode 100755 index 62eac61..c3eae96 --- a/common/mydefine.h +++ b/common/mydefine.h @@ -22,6 +22,12 @@ #define BACKUP_CLI_NAME "kybackup" +#define AUTO_BACKUP_UUID "{01234567-0123-0123-0123-0123456789ab}" +#define FACTORY_BACKUP_UUID "{00000000-0000-0000-0000-000000000000}" + +#define PATHS_USER_FILE ".user.txt" +#define EXCLUDE_PATHS_USER_FILE ".exclude.user.txt" + #define PID_STRING_LEN 1024 /** @@ -73,6 +79,8 @@ struct BackupWrapper { QStringList m_backupPaths; // 备份需要排除的路径 QStringList m_backupExcludePaths; + // 备份目标路径(前缀),在向移动设备备份时使用它来指定对应的移动设备路径 + QString m_prefixDestPath; // 备注信息 QString m_note; // 备份用户名 @@ -213,6 +221,7 @@ enum class BackupResult { // 根据操作类型动态创建处理类失败 NO_FOUND_DEALCLASS, + CHECK_ENV_SUCCESS, }; #endif // MYDEFINE_H diff --git a/common/mydusizetool.cpp b/common/mydusizetool.cpp old mode 100644 new mode 100755 index 693b1ca..9ebe588 --- a/common/mydusizetool.cpp +++ b/common/mydusizetool.cpp @@ -2,9 +2,10 @@ #include #include "utils.h" -MyDuSizeTool::MyDuSizeTool(QObject* parent) +MyDuSizeTool::MyDuSizeTool(QObject* parent) : + QObject(parent), + m_p(new QProcess(this)) { - m_p = new QProcess(this); connect(m_p, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(finished(int, QProcess::ExitStatus))); connect(m_p, &QProcess::readyReadStandardError, this, [&]() { QByteArray err = m_p->readAllStandardError(); diff --git a/common/mydusizetool.h b/common/mydusizetool.h old mode 100644 new mode 100755 diff --git a/common/mylittleparse.cpp b/common/mylittleparse.cpp old mode 100644 new mode 100755 diff --git a/common/mylittleparse.h b/common/mylittleparse.h old mode 100644 new mode 100755 diff --git a/common/reflect.cpp b/common/reflect.cpp old mode 100644 new mode 100755 diff --git a/common/reflect.h b/common/reflect.h old mode 100644 new mode 100755 diff --git a/common/singleton.h b/common/singleton.h old mode 100644 new mode 100755 diff --git a/common/spinlock_mutex.h b/common/spinlock_mutex.h old mode 100644 new mode 100755 diff --git a/common/utils.cpp b/common/utils.cpp old mode 100644 new mode 100755 index d03ca76..f05fced --- a/common/utils.cpp +++ b/common/utils.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include "mylittleparse.h" +#include "mydefine.h" QString Utils::m_sysRootPath = "/"; @@ -79,7 +81,7 @@ void Utils::customMessageHandler(QtMsgType type, const QMessageLogContext& conte file.open(QIODevice::ReadWrite | QIODevice::Append); QTextStream stream(&file); stream << strMessage << endl; - file.flush(); + stream.flush(); file.close(); } @@ -181,6 +183,28 @@ QString Utils::getBackupPartitionUuid() QString restoreUuid; parse.find("RECOVERY_DEV_UUID", restoreUuid); + if (restoreUuid.isEmpty()) { + QString fstab = Utils::m_sysRootPath + FSTAB_PATH; + fstab.replace("//", "/"); + QFile file(fstab); + if (file.exists()) { + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine(); + if (line.startsWith("UUID=") && line.contains("/backup")) { + int indexOfSpace = line.indexOf(QRegularExpression("[ \t]"), 0); + QString uuid = line.mid(0, indexOfSpace); + uuid.replace("UUID=", ""); + restoreUuid = uuid.trimmed(); + + break ; + } + } + } + } + } + return restoreUuid; } @@ -368,3 +392,37 @@ QStringList Utils::getFromExcludePathsFile() return list; } + +/** + * @brief 生成Uuid + * @return UUID + */ +QString Utils::createUuid() +{ + QString uuid; + do { + uuid = QUuid::createUuid().toString(); + } while (uuid == AUTO_BACKUP_UUID || uuid == FACTORY_BACKUP_UUID); + return uuid; +} + +/** + * @brief 将列表中内容写入指定文件中 + * @param fileName,文件全路径 + * @param lines,内容列表 + * @return true,成功写入;false,写入失败 + */ +bool Utils::writeFileByLines(const QString& fileName, const QStringList& lines) +{ + QFile file(fileName); + if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { + return false; + } + + QTextStream out(&file); + for (const QString& line : lines) { + out << line << endl; + } + file.close(); + return true; +} diff --git a/common/utils.h b/common/utils.h old mode 100644 new mode 100755 index 9243605..d32e5f7 --- a/common/utils.h +++ b/common/utils.h @@ -105,6 +105,20 @@ public: */ static bool isDirExist(const QString& fullDirName); + /** + * @brief 生成Uuid + * @return UUID + */ + static QString createUuid(); + + /** + * @brief 将列表中内容写入指定文件中 + * @param fileName,文件全路径 + * @param lines,内容列表 + * @return true,成功写入;false,写入失败 + */ + static bool writeFileByLines(const QString& fileName, const QStringList& lines); + private: // 系统根目录,默认"/" static QString m_sysRootPath;