diff --git a/backup-daemon/backup-daemon.pro b/backup-daemon/backup-daemon.pro index fd9bcc5..9c18348 100755 --- a/backup-daemon/backup-daemon.pro +++ b/backup-daemon/backup-daemon.pro @@ -7,6 +7,9 @@ CONFIG -= app_bundle CONFIG += link_pkgconfig +LIBS += -lblkid \ + -lkysec + # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the diff --git a/backup-daemon/backupmanager_adaptor.h b/backup-daemon/backupmanager_adaptor.h index ad82080..d283c28 100755 --- a/backup-daemon/backupmanager_adaptor.h +++ b/backup-daemon/backupmanager_adaptor.h @@ -55,6 +55,13 @@ class ManagerAdaptor: public QDBusAbstractAdaptor " \n" " \n" " \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" @@ -122,6 +129,8 @@ public Q_SLOTS: // METHODS int goRestore(BackupWrapper backupWrapper); int cancel(BackupWrapper backupWrapper); Q_SIGNALS: // SIGNALS + void backupFinished(bool result); + void progress(int in0, int in1); void sendBackupResult(bool result); void sendDeleteResult(bool result); void sendEnvCheckResult(int result); diff --git a/backup-daemon/main.cpp b/backup-daemon/main.cpp index a482667..bbd0516 100755 --- a/backup-daemon/main.cpp +++ b/backup-daemon/main.cpp @@ -30,9 +30,10 @@ int main(int argc, char *argv[]) qDebug() << QString("测试 begin"); BackupWrapper backupWrapper; + backupWrapper.m_backupName = "赵民勇test"; backupWrapper.m_backupExcludePaths = Utils::getFromExcludePathsFile(); MyBackupManager manager; - manager.checkEnv(backupWrapper); + manager.goBackup(backupWrapper); qDebug() << QString("测试 end"); // test end diff --git a/backup-daemon/mybackupmanager.cpp b/backup-daemon/mybackupmanager.cpp index 0f86d20..385cc1a 100755 --- a/backup-daemon/mybackupmanager.cpp +++ b/backup-daemon/mybackupmanager.cpp @@ -95,6 +95,9 @@ int MyBackupManager::goBackup(const BackupWrapper& backupWrapper) this->finished(); } }); + connect(worker, &Worker::progress, this, [&](int rate) { + emit this->progress(int(BackupState::WORKING), rate); + }); connect(worker, &Worker::workResult, this, [&] (bool result) { emit this->sendBackupResult(result); this->finished(); @@ -187,6 +190,7 @@ int MyBackupManager::getBackupState(bool& isActive) */ int MyBackupManager::cancel(const BackupWrapper& backupWrapper) { + Q_UNUSED(backupWrapper) return 0; } diff --git a/backup-daemon/mybackupmanager.h b/backup-daemon/mybackupmanager.h index c65b4f0..478e7a7 100755 --- a/backup-daemon/mybackupmanager.h +++ b/backup-daemon/mybackupmanager.h @@ -17,14 +17,21 @@ public: virtual ~MyBackupManager(); signals: - // 环境检查结果信号 - void sendEnvCheckResult(int result); + // 这3个信号供控制面板/自动更新等外围模块使用 // 开始备份结果信号 void sendStartBackupResult(int result); // 备份结果信号 void sendBackupResult(bool result); // 进度信号 void sendRate(int, int); + + // 模块内使用的信号 + // 进度信号 + void progress(int, int); + // 备份结果信号 + void backupFinished(bool result); + // 环境检查结果信号 + void sendEnvCheckResult(int result); // 还原结果信号 void sendRestoreResult(bool result); // 删除备份结果信号 diff --git a/backup-daemon/myprocess/calcbackupsize.cpp b/backup-daemon/myprocess/calcbackupsize.cpp index 45a965b..032d66a 100755 --- a/backup-daemon/myprocess/calcbackupsize.cpp +++ b/backup-daemon/myprocess/calcbackupsize.cpp @@ -15,6 +15,7 @@ CalcBackupSize::CalcBackupSize(QObject* parent) : }); connect(m_process, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) { + Q_UNUSED(error) m_process->kill(); }); @@ -89,7 +90,6 @@ void CalcBackupSize::parseResult() QString out(m_process->readAll()); QStringList lines = out.split("\n"); for (QString& line : lines) { - line.trimmed(); // 获取文件夹数目 // if (line.startsWith("Number of files:")) { // int indexOfDir = line.indexOf("dir: "); @@ -102,7 +102,7 @@ void CalcBackupSize::parseResult() // m_size += numOfDirs * 4096; // } if (line.startsWith("Total transferred file size: ")) { - m_size += line.replace("Total file size:", "").replace("bytes", "").replace(",","").trimmed().toLongLong(); + m_size += line.replace("Total transferred file size: ", "").replace("bytes", "").replace(",","").trimmed().toLongLong(); } } } @@ -114,6 +114,7 @@ void CalcBackupSize::parseResult() void CalcBackupSize::processFinish(int exitCode, QProcess::ExitStatus) { qDebug() << "CalcBackupSize::getCalcResult invoke begin"; + Q_UNUSED(exitCode) parseResult(); emit finished(m_size); diff --git a/backup-daemon/myprocess/rsyncpathtodirprocess.cpp b/backup-daemon/myprocess/rsyncpathtodirprocess.cpp index c11baa3..3f157b5 100755 --- a/backup-daemon/myprocess/rsyncpathtodirprocess.cpp +++ b/backup-daemon/myprocess/rsyncpathtodirprocess.cpp @@ -29,6 +29,7 @@ RsyncPathToDirProcess::RsyncPathToDirProcess(QObject *parent) : }); connect(m_p, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) { + Q_UNUSED(error) m_p->kill(); }); diff --git a/backup-daemon/parsebackuplist.cpp b/backup-daemon/parsebackuplist.cpp index 282e007..e21f4fd 100755 --- a/backup-daemon/parsebackuplist.cpp +++ b/backup-daemon/parsebackuplist.cpp @@ -301,15 +301,15 @@ void ParseBackupList::elementNodeToBackupPoint(const QDomElement& node, BackupPo * @param backupPoint, BackupPoint * @param node, QDomElement */ -void ParseBackupList::backupPointToElementNode(const BackupPoint& backupPoint, QDomElement& node) +void ParseBackupList::backupPointToElementNode(const BackupPoint& backupPoint, QDomDocument& doc, QDomNode& node) { - node.appendChild(createTextElement(COMMENT, backupPoint.m_backupName)); - node.appendChild(createTextElement(TIME, backupPoint.m_time)); - node.appendChild(createTextElement(UUID, backupPoint.m_uuid)); - node.appendChild(createTextElement(SIZE, backupPoint.m_size)); - node.appendChild(createTextElement(STATE, backupPoint.m_state)); - node.appendChild(createTextElement(TYPE, QString::number(backupPoint.m_type))); - node.appendChild(createTextElement(POSITION, QString::number(backupPoint.m_iPosition))); + node.appendChild(createTextElement(doc, COMMENT, backupPoint.m_backupName)); + node.appendChild(createTextElement(doc, TIME, backupPoint.m_time)); + node.appendChild(createTextElement(doc, UUID, backupPoint.m_uuid)); + node.appendChild(createTextElement(doc, SIZE, backupPoint.m_size)); + node.appendChild(createTextElement(doc, STATE, backupPoint.m_state)); + node.appendChild(createTextElement(doc, TYPE, QString::number(backupPoint.m_type))); + node.appendChild(createTextElement(doc, POSITION, QString::number(backupPoint.m_iPosition))); } /** @@ -318,13 +318,79 @@ void ParseBackupList::backupPointToElementNode(const BackupPoint& backupPoint, Q * @param text * @return text */ -QDomElement ParseBackupList::createTextElement(const QString& tagName, const QString& text) +QDomElement ParseBackupList::createTextElement(QDomDocument& doc, const QString& tagName, const QString& text) { - QDomElement node; - node.setTagName(tagName); - QDomText textNode; - textNode.setData(text); + QDomElement node = doc.createElement(tagName); + QDomText textNode = doc.createTextNode(text); node.appendChild(textNode); return node; } + +/** + * @brief 新增备份节点 + * @param backupPoint, 备份点信息 + * @return SUCCESS成功; XML_PARSE_ERR失败 + */ +ParseBackupList::ParseResult ParseBackupList::addItem(const BackupPoint& backupPoint) +{ + QDomDocument doc; + if (!Doc_setContent(doc)) + return XML_PARSE_ERR; + + QDomElement backupPointNode = doc.createElement(BACKUPPOINT); + backupPointToElementNode(backupPoint, doc, backupPointNode); + + QDomElement root = doc.documentElement(); + root.appendChild(backupPointNode); + + QFile xmlFile(m_xmlPath); + if (!xmlFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) + return FAIL; + + QTextStream out(&xmlFile); + doc.save(out, QDomNode::NodeType::CDATASectionNode); + xmlFile.close(); + return SUCCESS; +} + +/** + * @brief 更新备份点信息 + * @param backupPoint,新的备份点信息 + * @return SUCCESS成功; XML_PARSE_ERR失败 + */ +ParseBackupList::ParseResult ParseBackupList::updateItem(const BackupPoint & backupPoint) +{ + QDomDocument doc; + if (!Doc_setContent(doc)) + return XML_PARSE_ERR; + + QDomElement root = doc.documentElement(); + QDomNodeList list = root.childNodes(); + + for (int i = 0; i < list.count(); i++) { + QDomNode node = list.at(i); + if (!node.isElement()) + continue; + + QDomElement eleUuid = node.firstChildElement(UUID); + if (eleUuid.isNull() || backupPoint.m_uuid != eleUuid.text()) + continue; + + QDomElement newNode = doc.createElement(BACKUPPOINT); + backupPointToElementNode(backupPoint, doc, newNode); + root.replaceChild(newNode, node); + + break ; + } + + QFile xmlFile(m_xmlPath); + if (!xmlFile.open(QIODevice::WriteOnly)) { + return FAIL; + } + + QTextStream out(&xmlFile); + doc.save(out, QDomNode::NodeType::EntityReferenceNode); + xmlFile.close(); + return SUCCESS; +} diff --git a/backup-daemon/parsebackuplist.h b/backup-daemon/parsebackuplist.h index 24350aa..53a77be 100755 --- a/backup-daemon/parsebackuplist.h +++ b/backup-daemon/parsebackuplist.h @@ -67,6 +67,20 @@ public: */ BackupPoint getLastSysBackupPoint(); + /** + * @brief 新增备份节点 + * @param backupPoint, 备份点信息 + * @return SUCCESS成功; XML_PARSE_ERR失败 + */ + ParseResult addItem(const BackupPoint& backupPoint); + + /** + * @brief 更新备份点信息 + * @param backupPoint,新的备份点信息 + * @return SUCCESS成功; XML_PARSE_ERR失败 + */ + ParseResult updateItem(const BackupPoint & backupPoint); + inline QString getXmlPath() { return m_xmlPath; } private: @@ -75,8 +89,8 @@ private: bool Doc_setContent(QDomDocument& doc); void elementNodeToBackupPoint(const QDomElement& eleNode, BackupPoint& backupPoint); - void backupPointToElementNode(const BackupPoint& backupPoint, QDomElement& eleNode); - QDomElement createTextElement(const QString& tagName, const QString& text); + void backupPointToElementNode(const BackupPoint& backupPoint, QDomDocument& doc, QDomNode& eleNode); + QDomElement createTextElement(QDomDocument& doc, const QString& tagName, const QString& text); private: QString m_xmlPath; diff --git a/backup-daemon/systembackupproxy.cpp b/backup-daemon/systembackupproxy.cpp index 561d6a8..43d5fc6 100755 --- a/backup-daemon/systembackupproxy.cpp +++ b/backup-daemon/systembackupproxy.cpp @@ -1,10 +1,11 @@ #include "systembackupproxy.h" #include +#include #include +#include #include "../common/utils.h" #include "../common/mydusizetool.h" #include "mymountproxy.h" -#include "parsebackuplist.h" #include "myprocess/calcbackupsize.h" IMPLEMENT_DYNCREATE(SystemBackupProxy) @@ -13,11 +14,13 @@ SystemBackupProxy::SystemBackupProxy() { m_bSuccess = false; m_p = nullptr; + m_size = 0; } SystemBackupProxy::~SystemBackupProxy() { delete m_p; + m_p = nullptr; } /** @@ -99,6 +102,7 @@ bool SystemBackupProxy::checkFreeCapacity() // 1、计算待备份数据的大小 qint64 itotalSize = calcSizeForBackup(); + m_size = itotalSize; // 备份过程中会有一些临时文件产生,会占用一部分空间,故我们预留500M的空间 itotalSize += 500 * MB; @@ -243,6 +247,7 @@ void SystemBackupProxy::doBackup() } // 启动系统备份 + backupSystem(); qDebug() << "SystemBackupProxy::doBackup invoke end"; } @@ -255,12 +260,12 @@ bool SystemBackupProxy::doPrepare() { qDebug() << "SystemBackupProxy::doPrepare invoke begin"; + m_bSuccess = false; + // 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; @@ -277,7 +282,7 @@ bool SystemBackupProxy::doPrepare() QString userFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + PATHS_USER_FILE; userFile.replace("//", "/"); - if (Utils::writeFileByLines(userFile, m_backupWrapper.m_backupPaths)) { + 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; @@ -285,16 +290,53 @@ bool SystemBackupProxy::doPrepare() QString excludeUserFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + EXCLUDE_PATHS_USER_FILE; excludeUserFile.replace("//", "/"); - if (Utils::writeFileByLines(userFile, m_backupWrapper.m_backupPaths)) { + if (!Utils::writeFileByLines(excludeUserFile, m_backupWrapper.m_backupExcludePaths)) { emit checkResult(int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED)); qCritical() << QString("create file %1 failed !").arg(excludeUserFile) ; return false; } + // 3、记录/backup/snapshots/backuplist.xml文件 + if (!recordBackupPoint()) { + qCritical() << "add or update item to backuplist.xml failed !"; + return false; + } + qDebug() << "SystemBackupProxy::doPrepare invoke end"; return true; } +/** + * @brief 记录/backup/snapshots/backuplist.xml文件 + * @return true-成功;false-失败 + */ +bool SystemBackupProxy::recordBackupPoint() +{ + m_backupPoint.m_backupName = m_backupWrapper.m_backupName; + m_backupPoint.m_uuid = m_curUuid; + m_backupPoint.m_iPosition = m_backupWrapper.m_iPosition; + m_backupPoint.m_type = m_backupWrapper.m_type; + m_backupPoint.m_size = Utils::StringBySize(m_size); + m_backupPoint.m_time = QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"); + m_backupPoint.m_state = BACKUP_PARSE_STATE_FAIL_STRTING; + QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH; + xmlPath.replace("//", "/"); + ParseBackupList parse(xmlPath); + if (m_backupWrapper.m_uuid.isEmpty() || !m_backupWrapper.m_bIncrement) { + if (parse.addItem(m_backupPoint) != ParseBackupList::SUCCESS) { + emit checkResult(int(BackupResult::WRITE_STORAGEINFO_ADD_ITEM_FAIL)); + return false; + } + } else { + if (parse.updateItem(m_backupPoint) != ParseBackupList::SUCCESS) { + emit checkResult(int(BackupResult::WRITE_STORAGEINFO_UPDATE_ITEM_FAIL)); + return false; + } + } + + return true; +} + /** * @brief 备份/boot/efi * @return true,备份成功;false,备份失败 @@ -324,3 +366,71 @@ bool SystemBackupProxy::backupEfi() return result; } +/** + * @brief 备份系统 + * @return true,备份成功;false,备份失败 + */ +bool SystemBackupProxy::backupSystem() +{ + qDebug() << "SystemBackupProxy::backupSystem invoke begin"; + + QStringList args; + if (m_backupWrapper.m_bIncrement) { + if (m_backupWrapper.m_uuid.isEmpty()) { + // 新增增量备份点场景 + args = getRsyncArgs(SystemBackupScene::INC_SYSTEM_BACKUP); + } else { + // 在原来的备份点上增量备份场景 + args = getRsyncArgs(SystemBackupScene::INC_SYSTEM_BACKUP_AT_BASE); + } + } else { + // 全量备份场景 + args = getRsyncArgs(SystemBackupScene::SYSTEM_BACKUP); + } + + // 拼接备份源路径和目标路径 + QString srcPath = Utils::getSysRootPath(); + srcPath += "/"; + srcPath.replace("//", "/"); + args << srcPath; + QString destPath = m_destPath + "/"; + destPath.replace("//", "/"); + args << destPath; + + m_p = new RsyncPathToDirProcess(this); + connect(m_p, &RsyncPathToDirProcess::progress, this, &SystemBackupProxy::progress); + connect(m_p, &RsyncPathToDirProcess::finished, this, [&](bool result) { + if (result) { + m_backupPoint.m_state = BACKUP_PARSE_STATE_SUCCESS_STRTING; + QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH; + xmlPath.replace("//", "/"); + ParseBackupList parse(xmlPath); + parse.updateItem(m_backupPoint); + + Utils::writeBackupLog(m_backupPoint.m_time + "," + + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + "," + + m_backupWrapper.m_note + "," + m_backupPoint.m_size); + m_bSuccess = true; + } + emit this->workResult(result); + }); + m_p->start(args, false); + + do_kylin_security(m_destPath); + + qDebug() << "SystemBackupProxy::backupSystem invoke end"; + return true; +} + +void SystemBackupProxy::do_kylin_security(const QString& dstDir) +{ + int ret = 0; + ret = kysec_getstatus(); + if (ret > 0) { + QString seFilePath(dstDir + "/.exectl"); + QFile file(seFilePath); + file.open(QIODevice::WriteOnly); + file.close(); + } +} + diff --git a/backup-daemon/systembackupproxy.h b/backup-daemon/systembackupproxy.h index 480733a..fbb9bdf 100755 --- a/backup-daemon/systembackupproxy.h +++ b/backup-daemon/systembackupproxy.h @@ -3,6 +3,7 @@ #include "workerfactory.h" #include "myprocess/rsyncpathtodirprocess.h" +#include "parsebackuplist.h" class SystemBackupProxy : public Worker { @@ -50,6 +51,12 @@ private: */ QStringList getRsyncArgs(SystemBackupScene scene); + /** + * @brief 记录/backup/snapshots/backuplist.xml文件 + * @return true-成功;false-失败 + */ + bool recordBackupPoint(); + // 备份准备 bool doPrepare(); @@ -59,14 +66,23 @@ private: // 备份/boot/efi bool backupEfi(); + // 备份系统 + bool backupSystem(); + + void do_kylin_security(const QString& dstDir); + // 是否备份成功 bool m_bSuccess; // 当前备份uuid QString m_curUuid; // 当前备份目标目录 QString m_destPath; + // 当前备份所需空间大小 + qint64 m_size; // 备份进程 RsyncPathToDirProcess *m_p; + // 当前备份节点 + ParseBackupList::BackupPoint m_backupPoint; }; diff --git a/backup-daemon/workerfactory.cpp b/backup-daemon/workerfactory.cpp index 4842ab9..77dea36 100755 --- a/backup-daemon/workerfactory.cpp +++ b/backup-daemon/workerfactory.cpp @@ -35,7 +35,9 @@ void Worker::cancel() // 环境检测,个性化部分派生类去实现 bool Worker::checkEnvEx() -{} +{ + return true; +} // 任务处理,个性化部分派生类去实现 void Worker::doWorkEx() diff --git a/backup-daemon/workerfactory.h b/backup-daemon/workerfactory.h index 8a1da39..c554a84 100755 --- a/backup-daemon/workerfactory.h +++ b/backup-daemon/workerfactory.h @@ -18,6 +18,8 @@ public: signals: // 检测结果信号 void checkResult(int result); + // 进度百分比 + void progress(int currentRate); // 工作结果信号 void workResult(bool result); diff --git a/common/mydefine.h b/common/mydefine.h index c3eae96..5b32eef 100755 --- a/common/mydefine.h +++ b/common/mydefine.h @@ -13,6 +13,7 @@ #define BACKUP_XML_PATH "/backup/snapshots/backuplist.xml" #define EXCLUDE_FILE_PATH "/backup/snapshots/.exclude" #define CHECK_PATH "/backup/snapshots/check/data/" +#define BACKUP_LOG_TEXT_PATH "/backup/log.txt" #define BOOTINFO_PATH "/etc/.bootinfo" #define FSTAB_PATH "/etc/fstab" @@ -28,6 +29,11 @@ #define PATHS_USER_FILE ".user.txt" #define EXCLUDE_PATHS_USER_FILE ".exclude.user.txt" +#define BACKUP_PARSE_STATE_SUCCESS_STRTING "backup finished" +#define BACKUP_PARSE_STATE_FAIL_STRTING "backup unfinished" +#define BACKUP_PARSE_STATE_INC_SUCCESS_STRTING "inc backup finished" +#define BACKUP_PARSE_STATE_INC_FAIL_STRTING "inc backup unfinished" + #define PID_STRING_LEN 1024 /** diff --git a/common/utils.cpp b/common/utils.cpp index f05fced..f487c7c 100755 --- a/common/utils.cpp +++ b/common/utils.cpp @@ -13,6 +13,11 @@ #include #include #include +#include +#include +#include +#include + #include "mylittleparse.h" #include "mydefine.h" @@ -423,6 +428,85 @@ bool Utils::writeFileByLines(const QString& fileName, const QStringList& lines) for (const QString& line : lines) { out << line << endl; } + out.flush(); file.close(); return true; } + +/** + * @brief 判断文件是否存在 + * @param fileName 文件明 + * @return bool,true-存在;false-不存在 + * @author zhaominyong + * @since 2021/05/29 + */ +bool Utils::filsExists(const QString &fileName) +{ + struct stat buffer; + return (stat(fileName.toStdString().data(), &buffer) == 0); +} + +/** + * @brief 记录备份日志 + * @param line,日志内容 + * @return bool, true-成功;false-失败 + * @author zhaominyong + * @since 2021/05/29 + * @note + * 因为系统恢复成功后马上需要reboot,但是此时的文件缓存可能还未能落盘,故此增加此函数,其中调用了系统函数fdatasync确保缓存落盘 + */ +bool Utils::writeBackupLog(QString line) +{ + line = line + "\n"; + QString logFile = Utils::getSysRootPath() + BACKUP_LOG_TEXT_PATH; + logFile.replace("//", "/"); + std::string fileName(logFile.toStdString()); + // 判断文件是否存在 + bool exists = filsExists(logFile); + + std::unique_ptr fp(std::fopen(fileName.data(), "a+"), std::fclose); + + if (!fp) { + std::perror("file opening failed!"); + return false; + } + + if (!exists) { + std::fputs("#This file must not be deleted and it is for the backup tool.\n", fp.get()); + std::fputs("#0:new system backup\n", fp.get()); + std::fputs("#1:update system backup\n", fp.get()); + std::fputs("#2:new data backup\n", fp.get()); + std::fputs("#3:update data backup\n", fp.get()); + std::fputs("#4:restore system\n", fp.get()); + std::fputs("#5:retaining user data\n", fp.get()); + std::fputs("#6:restore data\n", fp.get()); + std::fputs("#8:delete backup\n", fp.get()); + std::fputs("#for example: 17-04-25 10:43:56,{uuidxxxxx},0,this is a note\n", fp.get()); + } + std::fputs(line.toStdString().data(), fp.get()); + std::fflush(fp.get()); + fdatasync(fileno(fp.get())); + + return true; +} + +/** + * @brief 将字节大小转换为GB等表示的字符串 + * @param size,qint64,空间大小,单位字节 + * @return GB/MB/KB等表示的字符串型大小 + */ +QString Utils::StringBySize(qint64 size) +{ +#define GB (1024 * 1024 * 1024) +#define MB (1024 * 1024) +#define KB (1024) + + float fcount = size * 1.0; + + if (size > GB) + return QString(QString::number(fcount / GB, 10, 2) + "GB"); + else if (size > MB) + return QString(QString::number(fcount / MB, 10, 2) + "MB"); + else + return QString(QString::number(fcount / KB, 10, 2) + "KB"); +} diff --git a/common/utils.h b/common/utils.h index d32e5f7..2c46a3a 100755 --- a/common/utils.h +++ b/common/utils.h @@ -119,6 +119,33 @@ public: */ static bool writeFileByLines(const QString& fileName, const QStringList& lines); + /** + * @brief 判断文件是否存在 + * @param fileName 文件明 + * @return bool,true-存在;false-不存在 + * @author zhaominyong + * @since 2021/05/29 + */ + static bool filsExists(const QString &fileName); + + /** + * @brief 记录备份日志 + * @param line,日志内容 + * @return bool, true-成功;false-失败 + * @author zhaominyong + * @since 2021/05/29 + * @note + * 因为系统恢复成功后马上需要reboot,但是此时的文件缓存可能还未能落盘,故此增加此函数,其中调用了系统函数fdatasync确保缓存落盘 + */ + static bool writeBackupLog(QString line); + + /** + * @brief 将字节大小转换为GB等表示的字符串 + * @param size,qint64,空间大小,单位字节 + * @return GB/MB/KB等表示的字符串型大小 + */ + static QString StringBySize(qint64 size); + private: // 系统根目录,默认"/" static QString m_sysRootPath; diff --git a/kybackup/backup_manager_interface.h b/kybackup/backup_manager_interface.h index 2cde03d..7a70d50 100644 --- a/kybackup/backup_manager_interface.h +++ b/kybackup/backup_manager_interface.h @@ -121,6 +121,8 @@ public Q_SLOTS: // METHODS } Q_SIGNALS: // SIGNALS + void backupFinished(bool result); + void progress(int in0, int in1); void sendBackupResult(bool result); void sendDeleteResult(bool result); void sendEnvCheckResult(int result);