重构版

This commit is contained in:
zhaominyong 2021-08-06 10:20:03 +08:00
parent 7d8ed8be11
commit 2f428f041d
34 changed files with 2861 additions and 0 deletions

View File

@ -0,0 +1,53 @@
QT += core
QT -= gui
QT += dbus
CONFIG += c++11 console
CONFIG -= app_bundle
CONFIG += link_pkgconfig
# 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
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
HEADERS += \
../common/mydefine.h \
../common/mylittleparse.h \
../common/reflect.h \
../common/singleton.h \
../common/spinlock_mutex.h \
../common/utils.h \
backupmanager_adaptor.h \
mybackupmanager.h \
mymountproxy.h \
myprocess/mountbackupprocess.h \
systembackupproxy.h \
workerfactory.h
SOURCES += \
../common/mydefine.cpp \
../common/mylittleparse.cpp \
../common/reflect.cpp \
../common/utils.cpp \
backupmanager_adaptor.cpp \
main.cpp \
mybackupmanager.cpp \
mymountproxy.cpp \
myprocess/mountbackupprocess.cpp \
systembackupproxy.cpp \
workerfactory.cpp
# Default rules for deployment.
# qnx: target.path = /tmp/$${TARGET}/bin
# else: unix:!android: target.path = /usr/bin
# !isEmpty(target.path): INSTALLS += target

View File

@ -0,0 +1,115 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.backup.manager.xml -i mybackupmanager.h -a ManagerAdaptor
*
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#include "backupmanager_adaptor.h"
#include <QtCore/QMetaObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
/*
* Implementation of adaptor class ManagerAdaptor
*/
ManagerAdaptor::ManagerAdaptor(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
// constructor
setAutoRelaySignals(true);
}
ManagerAdaptor::~ManagerAdaptor()
{
// destructor
}
int ManagerAdaptor::Mount_backup_partition()
{
// handle method call com.kylin.backup.manager.Mount_backup_partition
int out0;
QMetaObject::invokeMethod(parent(), "Mount_backup_partition", Q_RETURN_ARG(int, out0));
return out0;
}
void ManagerAdaptor::autoBackUpForSystemUpdate_noreturn(const QString &autobackup_name, const QString &create_note, const QString &inc_note, const QString &frontUserName, int frontUid)
{
// handle method call com.kylin.backup.manager.autoBackUpForSystemUpdate_noreturn
QMetaObject::invokeMethod(parent(), "autoBackUpForSystemUpdate_noreturn", Q_ARG(QString, autobackup_name), Q_ARG(QString, create_note), Q_ARG(QString, inc_note), Q_ARG(QString, frontUserName), Q_ARG(int, frontUid));
}
int ManagerAdaptor::checkEnv(BackupWrapper backupWrapper)
{
// handle method call com.kylin.backup.manager.checkEnv
int out0;
QMetaObject::invokeMethod(parent(), "checkEnv", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper));
return out0;
}
int ManagerAdaptor::deleteBackupPoint(BackupWrapper backupWrapper)
{
// handle method call com.kylin.backup.manager.deleteBackupPoint
int out0;
QMetaObject::invokeMethod(parent(), "deleteBackupPoint", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper));
return out0;
}
QString ManagerAdaptor::getBackupCommentForSystemUpdate(QString &state)
{
// handle method call com.kylin.backup.manager.getBackupCommentForSystemUpdate
//return static_cast<YourObjectType *>(parent())->getBackupCommentForSystemUpdate(state);
QString out0;
QMetaObject::invokeMethod(parent(), "getBackupCommentForSystemUpdate", Q_RETURN_ARG(QString, out0), Q_ARG(QString&, state));
return out0;
}
int ManagerAdaptor::getBackupState(bool &isActive)
{
// handle method call com.kylin.backup.manager.getBackupState
//return static_cast<YourObjectType *>(parent())->getBackupState(isActive);
int out0;
QMetaObject::invokeMethod(parent(), "getBackupState", Q_RETURN_ARG(int, out0), Q_ARG(bool&, isActive));
return out0;
}
int ManagerAdaptor::ghostBackup(BackupWrapper backupWrapper)
{
// handle method call com.kylin.backup.manager.ghostBackup
int out0;
QMetaObject::invokeMethod(parent(), "ghostBackup", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper));
return out0;
}
int ManagerAdaptor::goBackup(BackupWrapper backupWrapper)
{
// handle method call com.kylin.backup.manager.goBackup
int out0;
QMetaObject::invokeMethod(parent(), "goBackup", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper));
return out0;
}
int ManagerAdaptor::goRestore(BackupWrapper backupWrapper)
{
// handle method call com.kylin.backup.manager.goRestore
int out0;
QMetaObject::invokeMethod(parent(), "goRestore", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper));
return out0;
}
int ManagerAdaptor::cancel()
{
// handle method call com.kylin.backup.manager.goRestore
int out0;
QMetaObject::invokeMethod(parent(), "cancel", Q_RETURN_ARG(int, out0));
return out0;
}

View File

@ -0,0 +1,132 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.backup.manager.xml -i mybackupmanager.h -a ManagerAdaptor
*
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#ifndef MANAGERADAPTOR_H
#define MANAGERADAPTOR_H
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
#include "mybackupmanager.h"
QT_BEGIN_NAMESPACE
class QByteArray;
template<class T> class QList;
template<class Key, class Value> class QMap;
class QString;
class QStringList;
class QVariant;
QT_END_NAMESPACE
/*
* Adaptor class for interface com.kylin.backup.manager
*/
class ManagerAdaptor: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.kylin.backup.manager")
Q_CLASSINFO("D-Bus Introspection", ""
" <interface name=\"com.kylin.backup.manager\">\n"
" <signal name=\"sendEnvCheckResult\">\n"
" <arg direction=\"out\" type=\"i\" name=\"result\"/>\n"
" </signal>\n"
" <signal name=\"sendStartBackupResult\">\n"
" <arg direction=\"out\" type=\"i\" name=\"result\"/>\n"
" </signal>\n"
" <signal name=\"sendBackupResult\">\n"
" <arg direction=\"out\" type=\"b\" name=\"result\"/>\n"
" </signal>\n"
" <signal name=\"sendRate\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" </signal>\n"
" <signal name=\"sendRestoreResult\">\n"
" <arg direction=\"out\" type=\"b\" name=\"result\"/>\n"
" </signal>\n"
" <signal name=\"sendDeleteResult\">\n"
" <arg direction=\"out\" type=\"b\" name=\"result\"/>\n"
" </signal>\n"
" <signal name=\"sendGhostBackupResult\">\n"
" <arg direction=\"out\" type=\"b\" name=\"result\"/>\n"
" </signal>\n"
" <method name=\"Mount_backup_partition\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" </method>\n"
" <method name=\"autoBackUpForSystemUpdate_noreturn\">\n"
" <arg direction=\"in\" type=\"s\" name=\"autobackup_name\"/>\n"
" <arg direction=\"in\" type=\"s\" name=\"create_note\"/>\n"
" <arg direction=\"in\" type=\"s\" name=\"inc_note\"/>\n"
" <arg direction=\"in\" type=\"s\" name=\"frontUserName\"/>\n"
" <arg direction=\"in\" type=\"i\" name=\"frontUid\"/>\n"
" </method>\n"
" <method name=\"getBackupCommentForSystemUpdate\">\n"
" <arg direction=\"out\" type=\"s\"/>\n"
" <arg direction=\"out\" type=\"s\" name=\"state\"/>\n"
" </method>\n"
" <method name=\"getBackupState\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <arg direction=\"out\" type=\"b\" name=\"isActive\"/>\n"
" </method>\n"
" <method name=\"checkEnv\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <annotation value=\"BackupWrapper\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
" <arg direction=\"in\" type=\"a(i)\" name=\"backupWrapper\"/>\n"
" </method>\n"
" <method name=\"goBackup\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <annotation value=\"BackupWrapper\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
" <arg direction=\"in\" type=\"a(i)\" name=\"backupWrapper\"/>\n"
" </method>\n"
" <method name=\"goRestore\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <annotation value=\"BackupWrapper\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
" <arg direction=\"in\" type=\"a(i)\" name=\"backupWrapper\"/>\n"
" </method>\n"
" <method name=\"deleteBackupPoint\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <annotation value=\"BackupWrapper\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
" <arg direction=\"in\" type=\"a(i)\" name=\"backupWrapper\"/>\n"
" </method>\n"
" <method name=\"ghostBackup\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" <annotation value=\"BackupWrapper\" name=\"org.qtproject.QtDBus.QtTypeName.In0\"/>\n"
" <arg direction=\"in\" type=\"a(i)\" name=\"backupWrapper\"/>\n"
" </method>\n"
" <method name=\"cancel\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
" </method>\n"
" </interface>\n"
"")
public:
ManagerAdaptor(QObject *parent);
virtual ~ManagerAdaptor();
public: // PROPERTIES
public Q_SLOTS: // METHODS
int Mount_backup_partition();
void autoBackUpForSystemUpdate_noreturn(const QString &autobackup_name, const QString &create_note, const QString &inc_note, const QString &frontUserName, int frontUid);
int checkEnv(BackupWrapper backupWrapper);
int deleteBackupPoint(BackupWrapper backupWrapper);
QString getBackupCommentForSystemUpdate(QString &state);
int getBackupState(bool &isActive);
int ghostBackup(BackupWrapper backupWrapper);
int goBackup(BackupWrapper backupWrapper);
int goRestore(BackupWrapper backupWrapper);
int cancel();
Q_SIGNALS: // SIGNALS
void sendBackupResult(bool result);
void sendDeleteResult(bool result);
void sendEnvCheckResult(int result);
void sendGhostBackupResult(bool result);
void sendRate(int in0, int in1);
void sendRestoreResult(bool result);
void sendStartBackupResult(int result);
};
#endif

View File

@ -0,0 +1,70 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="com.kylin.backup.manager">
<signal name="sendEnvCheckResult">
<arg name="result" type="i" direction="out"/>
</signal>
<signal name="sendStartBackupResult">
<arg name="result" type="i" direction="out"/>
</signal>
<signal name="sendBackupResult">
<arg name="result" type="b" direction="out"/>
</signal>
<signal name="sendRate">
<arg type="i" direction="out"/>
<arg type="i" direction="out"/>
</signal>
<signal name="sendRestoreResult">
<arg name="result" type="b" direction="out"/>
</signal>
<signal name="sendDeleteResult">
<arg name="result" type="b" direction="out"/>
</signal>
<signal name="sendGhostBackupResult">
<arg name="result" type="b" direction="out"/>
</signal>
<method name="Mount_backup_partition">
<arg type="i" direction="out"/>
</method>
<method name="autoBackUpForSystemUpdate_noreturn">
<arg name="autobackup_name" type="s" direction="in"/>
<arg name="create_note" type="s" direction="in"/>
<arg name="inc_note" type="s" direction="in"/>
<arg name="frontUserName" type="s" direction="in"/>
<arg name="frontUid" type="i" direction="in"/>
</method>
<method name="getBackupCommentForSystemUpdate">
<arg type="s" direction="out"/>
<arg name="state" type="s" direction="out"/>
</method>
<method name="getBackupState">
<arg type="i" direction="out"/>
<arg name="isActive" type="b" direction="out"/>
</method>
<method name="checkEnv">
<arg type="i" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="BackupWrapper"/>
<arg name="backupWrapper" type="a(i)" direction="in"/>
</method>
<method name="goBackup">
<arg type="i" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="BackupWrapper"/>
<arg name="backupWrapper" type="a(i)" direction="in"/>
</method>
<method name="goRestore">
<arg type="i" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="BackupWrapper"/>
<arg name="backupWrapper" type="a(i)" direction="in"/>
</method>
<method name="deleteBackupPoint">
<arg type="i" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="BackupWrapper"/>
<arg name="backupWrapper" type="a(i)" direction="in"/>
</method>
<method name="ghostBackup">
<arg type="i" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="BackupWrapper"/>
<arg name="backupWrapper" type="a(i)" direction="in"/>
</method>
</interface>
</node>

46
backup-daemon/main.cpp Normal file
View File

@ -0,0 +1,46 @@
#include <QCoreApplication>
#include <QTextCodec>
#include "../common/utils.h"
#include "../common/mydefine.h"
#include "backupmanager_adaptor.h"
// test begin
#include "../common/reflect.h"
#include "mymountproxy.h"
// test end
int main(int argc, char *argv[])
{
// 以防客户端传入的参数中的中文信息乱码
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QCoreApplication a(argc, argv);
a.setApplicationName("backup-daemon");
a.setApplicationVersion("4.0.14");
// 初始化日志
QString qsAppPath = QCoreApplication::applicationDirPath();
Utils::initSysRootPath(qsAppPath);
qInstallMessageHandler(Utils::customMessageHandler);
// test begin
//MyMountProxy * proxy = (MyMountProxy*)Reflect::createObject("MyMountProxy");
//proxy->mountBackupPartition();
BackupWrapper backupWrapper;
MyBackupManager manager;
manager.checkEnv(backupWrapper);
// test end
MyBackupManager* backup_deamon = new MyBackupManager;
new ManagerAdaptor(backup_deamon);
QDBusConnection conn = QDBusConnection::systemBus();
if (!conn.registerService("com.kylin.backup")) {
qDebug() << conn.lastError().message();
}
conn.registerObject("/", backup_deamon);
return a.exec();
}

View File

@ -0,0 +1,212 @@
/**
* brief moveToThread中去执行
*/
#include <mutex>
#include "mybackupmanager.h"
#include "../common/utils.h"
#include "mymountproxy.h"
#include "workerfactory.h"
/**
* @brief
*/
MyBackupManager::MyBackupManager()
{
// 注册BackupWrapper类型之后qdbus接口才能使用
BackupWrapper::registerMetaType();
}
/**
* @brief
*/
MyBackupManager::~MyBackupManager()
{
if (workerThread.isRunning()) {
workerThread.quit();
workerThread.wait();
}
}
/**
* @brief backup分区
* @return
*/
int MyBackupManager::Mount_backup_partition()
{
MyMountProxy mymount;
return int(mymount.mountBackupPartition());
}
/**
* @brief
* @param backupWrapper
* @return
*/
int MyBackupManager::checkEnv(const BackupWrapper& backupWrapper)
{
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, &MyBackupManager::sendEnvCheckResult);
connect(worker, &Worker::checkResult, this, &MyBackupManager::finished);
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::started, worker, &Worker::checkEnv);
connect(&workerThread, &QThread::finished, worker, &Worker::deleteLater);
return int(BackupResult::BACKUP_RESULT_INIT);
}
/**
* @brief
* @param backupWrapper
* @return
*/
int MyBackupManager::goBackup(const BackupWrapper& backupWrapper)
{
Q_UNUSED(backupWrapper)
return 0;
}
/**
* @brief
* @param backupWrapper
* @return
*/
int MyBackupManager::goRestore(const BackupWrapper& backupWrapper)
{
Q_UNUSED(backupWrapper)
return 0;
}
/**
* @brief
* @param backupWrapper
* @return
*/
int MyBackupManager::deleteBackupPoint(const BackupWrapper& backupWrapper)
{
Q_UNUSED(backupWrapper)
return 0;
}
/**
* @brief ghost镜像
* @param backupWrapper
* @return
*/
int MyBackupManager::ghostBackup(const BackupWrapper& backupWrapper)
{
Q_UNUSED(backupWrapper)
return 0;
}
/**
* @brief
* @param autobackup_name
* @param create_note
* @param inc_note
* @param frontUserName
* @param frontUid id
*/
void MyBackupManager::autoBackUpForSystemUpdate_noreturn(const QString& autobackup_name, const QString& create_note, const QString& inc_note, const QString& frontUserName, int frontUid)
{
Q_UNUSED(autobackup_name)
Q_UNUSED(create_note)
Q_UNUSED(inc_note)
Q_UNUSED(frontUserName)
Q_UNUSED(frontUid)
return ;
}
/**
* @brief
* @param state
* @return
*/
QString MyBackupManager::getBackupCommentForSystemUpdate(QString& state)
{
Q_UNUSED(state)
return "";
}
/**
* @brief
* @param isActive
* @return
*/
int MyBackupManager::getBackupState(bool& isActive)
{
Q_UNUSED(isActive)
return 0;
}
/**
* @brief
*/
int MyBackupManager::cancel()
{
return 0;
}
/**
* @brief
*/
void MyBackupManager::finished()
{
if (workerThread.isRunning()) {
workerThread.quit();
workerThread.wait();
}
unlock();
}
/**
* @brief
* @param frontUidid
* @return bool
*/
bool MyBackupManager::lock(int frontUid)
{
std::lock_guard<spinlock_mutex> lock(m_mutex);
int lock_file_fd = Utils::lockProgram(frontUid);
if (lock_file_fd < 0) {
Utils::rmLockFile();
return false;
}
m_fdLockFile = lock_file_fd;
m_backupState = BackupState::PREPARING;
m_isActive = true;
return true;
}
/**
* @brief
* @return bool
*/
bool MyBackupManager::unlock()
{
std::lock_guard<spinlock_mutex> lock(m_mutex);
Utils::unLockProgram(m_fdLockFile);
m_fdLockFile = -1;
m_backupState = BackupState::BACKUP_STATE_INIT;
m_isActive = false;
return true;
}

View File

@ -0,0 +1,78 @@
#ifndef MYBACKUPMANAGER_H
#define MYBACKUPMANAGER_H
#include <QObject>
#include <QtDBus/QDBusVariant>
#include <QHash>
#include <QThread>
#include "../common/mydefine.h"
#include "../common/spinlock_mutex.h"
class MyBackupManager : public QObject {
Q_OBJECT
// Q_CLASSINFO("D-Bus Interface", "com.kylin.backup.manager")
public:
explicit MyBackupManager();
virtual ~MyBackupManager();
signals:
// 环境检查结果信号
void sendEnvCheckResult(int result);
// 开始备份结果信号
void sendStartBackupResult(int result);
// 备份结果信号
void sendBackupResult(bool result);
// 进度信号
void sendRate(int, int);
// 还原结果信号
void sendRestoreResult(bool result);
// 删除备份结果信号
void sendDeleteResult(bool result);
// ghost备份结果信号
void sendGhostBackupResult(bool result);
public slots:
// 备份分区挂载
int Mount_backup_partition();
// 环境检测
int checkEnv(const BackupWrapper& backupWrapper);
// 备份
int goBackup(const BackupWrapper& backupWrapper);
// 还原
int goRestore(const BackupWrapper& backupWrapper);
// 删除备份
int deleteBackupPoint(const BackupWrapper& backupWrapper);
// ghost镜像
int ghostBackup(const BackupWrapper& backupWrapper);
// 控制面板调用的备份接口,重构暂时先兼容以前的老接口
void autoBackUpForSystemUpdate_noreturn(const QString& autobackup_name, const QString& create_note, const QString& inc_note, const QString& frontUserName, int frontUid);
// 控制面板调用的获取系统备份接口
QString getBackupCommentForSystemUpdate(QString& state);
// 获取备份状态
int getBackupState(bool& isActive);
// 取消操作
int cancel();
// 任务结束
void finished();
private:
// 锁定
bool lock(int frontUid);
// 解锁
bool unlock();
// 自旋锁
spinlock_mutex m_mutex;
private:
// 锁文件描述符
int m_fdLockFile = -1;
// 备份还原状态
BackupState m_backupState = BackupState::BACKUP_STATE_INIT;
// 是否活动的,兼容以前用的,和m_backupState的实际使用功能有重复
bool m_isActive = false;
// 工作者线程
QThread workerThread;
};
#endif // MYBACKUPMANAGER_H

View File

@ -0,0 +1,40 @@
#include <QtDebug>
#include <QDir>
#include "mymountproxy.h"
#include "../common/utils.h"
MyMountProxy::MyMountProxy(QObject* parent) : QObject(parent)
{
m_processMount = new MountBackupProcess(this);
}
MyMountProxy::MountResult MyMountProxy::mountBackupPartition()
{
QString backupPartitionUuid = Utils::getBackupPartitionUuid();
if (backupPartitionUuid.isEmpty()) {
qCritical("can't open /etc/.bootinfo or can't get RECOVERY_DEV_UUID");
return MyMountProxy::MountResult::CANNOT_GET_BACKUPUUID;
}
QString rootPath = Utils::getSysRootPath();
QString backPath = rootPath + BACKUP_PATH;
backPath.replace("//", "/");
Utils::mkpath(backPath);
bool res = m_processMount->Do(backupPartitionUuid);
if (res) {
QString snapshotsPath = rootPath + BACKUP_SNAPSHOTS_PATH;
snapshotsPath.replace("//", "/");
Utils::mkpath(snapshotsPath);
if (!Utils::generateExcludePathsFile()) {
qCritical("mount success, but generate some important file failed!");
return MyMountProxy::MountResult::GENERATE_IMPORT_FILE_FAIL;
}
return MyMountProxy::MountResult::MOUNTED;
}
return MyMountProxy::MountResult::NO_MOUNTED;
}

View File

@ -0,0 +1,28 @@
#ifndef MYMOUNTPROXY_H
#define MYMOUNTPROXY_H
#include <QObject>
#include "myprocess/mountbackupprocess.h"
class MyMountProxy : public QObject {
Q_OBJECT
public:
// 为兼容旧版本对外提供的接口,此处结构前面暂时不变,只在后面增加
enum class MountResult {
MOUNT_RESULT_INIT,
CANNOT_GET_BACKUPUUID,
NO_BLKID_EXIST,
NO_MOUNTED,
GENERATE_IMPORT_FILE_FAIL,
MOUNTED
};
MyMountProxy(QObject* parent = nullptr);
MountResult mountBackupPartition();
private:
MountBackupProcess* m_processMount;
};
#endif // MYMOUNTPROXY_H

View File

@ -0,0 +1,50 @@
#ifndef MOUNTBACKUPPROCESS_CPP
#define MOUNTBACKUPPROCESS_CPP
#include <QFile>
#include <QtDebug>
#include "mountbackupprocess.h"
#include "../../common/mydefine.h"
#include "../../common/utils.h"
MountBackupProcess::MountBackupProcess(QObject* parent)
: QObject(parent)
, m_p(new QProcess(this))
{
connect(m_p, &QProcess::readyReadStandardError, this, [&]() {
QByteArray err = m_p->readAllStandardError();
qCritical("%s", err.data());
});
}
bool MountBackupProcess::Do(const QString& diskUuid)
{
QString rootPath(Utils::getSysRootPath());
// 若备份路径下的xml已经存在则说明已经挂载过了
QString backupXmlPath = rootPath + BACKUP_XML_PATH;
backupXmlPath.replace("//", "/");
QFile file(backupXmlPath);
if (file.exists())
return true;
QStringList arguments;
QString backupPartion = rootPath + BACKUP_PATH;
backupPartion.replace("//","/");
arguments << QString("-o") << QString("rw") << QString("/dev/disk/by-uuid/%1").arg(diskUuid) << backupPartion;
m_p->start("mount", arguments);
if (!m_p->waitForStarted()) {
qFatal("mount rw /backup process start failed!");
return false;
}
if (!m_p->waitForFinished()) {
qFatal("mount rw backup process end failed!");
return false;
}
return true;
}
#endif // MOUNTBACKUPPROCESS_CPP

View File

@ -0,0 +1,19 @@
#ifndef MOUNTBACKUPPROCESS_H
#define MOUNTBACKUPPROCESS_H
#include <QProcess>
class MountBackupProcess : public QObject {
Q_OBJECT
public:
MountBackupProcess(QObject* parent = nullptr);
bool Do(const QString& diskUuid);
private:
QProcess* m_p;
};
#endif // MOUNTBACKUPPROCESS_H

View File

@ -0,0 +1,26 @@
#include "systembackupproxy.h"
#include <QDebug>
#include "../common/utils.h"
IMPLEMENT_DYNCREATE(SystemBackupProxy)
SystemBackupProxy::SystemBackupProxy(QObject * parent) :
Worker(parent)
{}
SystemBackupProxy::~SystemBackupProxy()
{}
void SystemBackupProxy::checkEnvEx()
{
qDebug() << "SystemBackupProxy::checkEnv invoke begin";
emit checkResult((int)BackupResult::BACKUP_START_SUCCESS);
qDebug() << "SystemBackupProxy::checkEnv invoke end";
}
void SystemBackupProxy::doWorkEx()
{}
void SystemBackupProxy::cancelEx()
{}

View File

@ -0,0 +1,25 @@
#ifndef SYSTEMBACKUPPROXY_H
#define SYSTEMBACKUPPROXY_H
#include "workerfactory.h"
class SystemBackupProxy : public Worker
{
Q_OBJECT
DECLARE_DYNCREATE(SystemBackupProxy)
public:
SystemBackupProxy(QObject * parent = nullptr);
virtual ~SystemBackupProxy();
public:
// 环境检测
virtual void checkEnvEx();
// 任务处理
virtual void doWorkEx();
// 任务取消
virtual void cancelEx();
};
#endif // SYSTEMBACKUPPROXY_H

View File

@ -0,0 +1,117 @@
#include "workerfactory.h"
#include <QString>
Worker::Worker(QObject* parent) :
QObject(parent)
{}
Worker::~Worker()
{}
//
/**
* @brief
*/
void Worker::checkEnv()
{
checkEnvEx();
}
/**
* @brief
*/
void Worker::doWork()
{
doWorkEx();
}
/**
* @brief
*/
void Worker::cancel()
{
cancelEx();
}
// 环境检测,个性化部分派生类去实现
void Worker::checkEnvEx()
{}
// 任务处理,个性化部分派生类去实现
void Worker::doWorkEx()
{}
// 任务取消,个性化部分派生类去实现
void Worker::cancelEx()
{}
/**
* @brief
* @param type ,
* @param position U盘备份: 0-1-
* @return Worker派生类对象指针
*/
Worker * WorkerFactory::createWorker(int type, int position)
{
QString className;
switch (type) {
case BackupType::BACKUP_SYSTEM:
case BackupType::INC_BACKUP_SYSTEM:
if (BackupPosition::UDISK == position) {
className = "UDiskSystemBackupProxy";
} else {
className = "SystemBackupProxy";
}
break;
case BackupType::AUTO_BACKUP_SYSTEM:
className = "AutoSystemBackupProxy";
break;
case BackupType::RESTORE_SYSTEM:
case BackupType::RESTORE_SYSTEM_WITH_DATA:
if (BackupPosition::UDISK == position) {
className = "UDiskSystemRestoreProxy";
} else {
className = "SystemRestoreProxy";
}
break;
case BackupType::BACKUP_DATA:
case BackupType::INC_BACKUP_DATA:
if (BackupPosition::UDISK == position) {
className = "UDiskDataBackupProxy";
} else {
className = "DataBackupProxy";
}
break;
case BackupType::RESTORE_DATA:
if (BackupPosition::UDISK == position) {
className = "UDiskDataRestoreProxy";
} else {
className = "DataRestoreProxy";
}
break;
case BackupType::DELETE_BACKUP:
if (BackupPosition::UDISK == position) {
className = "UDiskDeleteProxy";
} else {
className = "DeleteProxy";
}
break;
case BackupType::GHOST_IMAGE:
if (BackupPosition::UDISK == position) {
className = "UDiskGhostProxy";
} else {
className = "GhostProxy";
}
break;
default:
break;
}
if (className.isEmpty()) {
return nullptr;
}
Worker * p = qobject_cast<Worker *>(Reflect::createObject(className));
return p;
}

View File

@ -0,0 +1,66 @@
#ifndef WORKERFACTORY_H
#define WORKERFACTORY_H
#include <QObject>
#include "../common/mydefine.h"
#include "../common/reflect.h"
/**
* @brief
*/
class Worker : public QObject
{
Q_OBJECT
public:
Worker(QObject* parent = nullptr);
virtual ~Worker();
signals:
// 检测结果信号
void checkResult(int result);
// 工作结果信号
void workResult(bool result);
public slots:
// 环境检测
void checkEnv();
// 任务处理
void doWork();
// 任务取消
void cancel();
protected:
// 环境检测,个性化部分派生类去实现
virtual void checkEnvEx();
// 任务处理,个性化部分派生类去实现
virtual void doWorkEx();
// 任务取消,个性化部分派生类去实现
virtual void cancelEx();
public:
void setParam(const BackupWrapper& backupWrapper) { m_backupWrapper = backupWrapper; }
protected:
BackupWrapper m_backupWrapper;
};
/**
* @brief
*/
class WorkerFactory
{
public:
/**
* @brief
* @param type ,
* @param position U盘备份: 0-1-
* @return Worker派生类对象指针
*/
static Worker * createWorker(int type, int position);
};
#endif // WORKERFACTORY_H

32
common/mydefine.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "mydefine.h"
#include <QDBusMetaType>
// Marshall the MyStructure data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const BackupWrapper &backupWrapper)
{
argument.beginStructure();
argument << backupWrapper.m_type << backupWrapper.m_comment << backupWrapper.m_backupName
<< backupWrapper.m_uuid << backupWrapper.m_backupPaths << backupWrapper.m_backupExcludePaths
<< backupWrapper.m_note << backupWrapper.m_frontUserName << backupWrapper.m_frontUid
<< backupWrapper.m_gid;
argument.endStructure();
return argument;
}
// Retrieve the MyStructure data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, BackupWrapper &backupWrapper)
{
argument.beginStructure();
argument >> backupWrapper.m_type >> backupWrapper.m_comment >> backupWrapper.m_backupName
>> backupWrapper.m_uuid >> backupWrapper.m_backupPaths >> backupWrapper.m_backupExcludePaths
>> backupWrapper.m_note >> backupWrapper.m_frontUserName >> backupWrapper.m_frontUid
>> backupWrapper.m_gid;
argument.endStructure();
return argument;
}
void BackupWrapper::registerMetaType()
{
qRegisterMetaType<BackupWrapper>("BackupWrapper");
qDBusRegisterMetaType<BackupWrapper>();
}

216
common/mydefine.h Normal file
View File

@ -0,0 +1,216 @@
#ifndef MYDEFINE_H
#define MYDEFINE_H
#include <QString>
#include <QStringList>
#include <QMetaType>
#include <QDBusArgument>
#define DEFAULT_APP_PATH "/usr/bin"
#define LOCK_FILE "/tmp/lock/kylin-backup.lock"
#define BACKUP_XML_PATH "/backup/snapshots/backuplist.xml"
#define BOOTINFO_PATH "/etc/.bootinfo"
#define BACKUP_PATH "/backup"
#define BACKUP_SNAPSHOTS_PATH "/backup/snapshots"
#define EXCLUDE_FILE_PATH "/backup/snapshots/.exclude"
#define FSTAB_PATH "/etc/fstab"
#define BACKUP_CLI_NAME "kybackup"
#define PID_STRING_LEN 1024
/**
* @brief
*/
enum BackupType {
// 系统备份
BACKUP_SYSTEM = 0,
// 增量系统备份
INC_BACKUP_SYSTEM = 1,
// 数据备份
BACKUP_DATA = 2,
// 增量数据备份
INC_BACKUP_DATA = 3,
// 系统还原
RESTORE_SYSTEM = 4,
// 保留用户数据还原
RESTORE_SYSTEM_WITH_DATA = 5,
// 数据还原
RESTORE_DATA = 6,
// 增量数据还原,实际没有这个类型,为兼容以前的数据仍然保留
INC_RESTORE_DATA = 7,
// 删除备份点
DELETE_BACKUP = 8,
// ghost镜像
GHOST_IMAGE = 9,
// 自动升级模块的自动备份
AUTO_BACKUP_SYSTEM = 10,
// 仅仅初始化BackupType枚举类变量用没有用于持久化不用固定其值
BACKUP_TYPE_INIT,
};
/**
* @brief
*/
struct BackupWrapper {
// 操作类型,如:系统备份, 系统还原
int m_type = 0;
// 本地备份还是U盘备份: 0-本地备份1-移动设备备份
int m_iPosition = 0;
// 备份名称,用于识别备份的,默认是时间
QString m_comment;
// 备份名称用来替换m_comment
QString m_backupName;
// 备份或还原指定的UUID
QString m_uuid;
// 待备份目录
QStringList m_backupPaths;
// 备份需要排除的路径
QStringList m_backupExcludePaths;
// 备注信息
QString m_note;
// 备份用户名
QString m_frontUserName;
// 备份用户id
int m_frontUid = -1;
// 备份用户所属组id
int m_gid = -1;
static void registerMetaType();
};
Q_DECLARE_METATYPE(BackupWrapper)
extern QDBusArgument &operator<<(QDBusArgument &argument, const BackupWrapper &backupWrapper);
extern const QDBusArgument &operator>>(const QDBusArgument &argument, BackupWrapper &backupWrapper);
/**
* @brief
*/
enum class BackupState {
// 准备中
PREPARING = 1,
// 工作中
WORKING,
// 空闲状态
BACKUP_STATE_INIT = 99
};
/**
* @brief
*/
enum BackupPosition
{
LOCAL,
UDISK,
};
/**
* @brief
* @note
*/
enum class BackupResult {
// 备份初始
BACKUP_RESULT_INIT,
// /etc/.bootinfo读取失败
ETC_BOOTINFO_READ_FAIL,
// /etc/fstab不存在
FSTAB_IS_NOT_EXIST,
// 文件锁定应用失败
LOCK_PROGRAM_FAIL,
//有其他正在进行的备份或者还原
OTHER_BACKUP_OR_RESTORE_RUNNING,
// 有删除任务正在进行
RM_RUNNING,
// 正在制作镜像
MKSQUASHFS_RUNNING,
// 设备uuid不存在
NO_BLKID_EXIST,
// 挂载/backup分区失败
BACKUP_PARTITION_MOUNT_FAIL,
// 生成备份导入文件失败
GENERATE_BACKUP_IMPORT_FILE_FAIL,
// /backup/current目录不存在
BACKUP_CURRENT_DIR_IS_NOT_EXIST,
// /backup/snapshots目录不存在
BACKUP_SNAPSHOTS_DIR_IS_NOT_EXIST,
// /backup/snapshots/backuplist.xml文件不存在或打开失败
BACKUP_STORAGEINFO_FILE_FAIL_TO_OPEN,
// /backup/snapshots/backuplist.xml格式不正确
BACKUP_STORAGEINFO_IS_NOT_CORRECT,
// 写入 /backup/snapshots/backuplist.xml 失败
WRITE_STORAGEINFO_ADD_ITEM_FAIL,
// 修改 /backup/snapshots/backuplist.xml 失败
WRITE_STORAGEINFO_UPDATE_ITEM_FAIL,
// 增量备份未找到对应的uuid
INC_NOT_FOUND_UUID,
// 增量备份未找到对应的目录
INC_NOT_FOUND_DIR,
// 将备份路径写入/backup/snapshots/{uuid}/.user.txt失败
WRITE_BACKUP_PATHS_TO_USER_FAILED,
// 将备份路径写入/backup/snapshots/{uuid}/.exclude.user.txt失败
WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED,
// /backup备份空间不足
BACKUP_CAPACITY_IS_NOT_ENOUGH,
// U盘文件系统是只读的
UDISK_FILESYSTEM_IS_READONLY,
// u盘中创建目录/backup/snapshots失败
UDISK_STH_ERROR,
// u盘文件系统是vfat格式容量有限或单个文件大小有限
UDISK_FILESYSTEM_TYPE_IS_VFAT,
// DU计算大小失败
DU_ERR,
// 向U盘备份时先压缩到本地成img文件本地备份分区空间不足
BACKUP_CAPACITY_FOR_UDISKIMG_IS_NOT_ENOUGH,
// U盘容量不足
UDISK_CAPACITY_IS_NOT_ENOUGH,
// /boot/efi同步失败
EFI_RSYNC_FAIL,
// 备份启动失败
BACKUP_PROCESS_START_FAIL,
// 备份失败
BACKUP_PROCESS_DO_FAIL,
// 备份进程成功启动
BACKUP_START_SUCCESS,
// 备份成功,信号未使用此结果
BACKUP_DO_SUCCESS,
// 还原初始
RESTORE_RESULT_INIT,
// 还原目录准备失败
RESTOREDIR_PREPARE_FAILED,
// 还原进程开启失败
RESTORE_PROCESS_START_FAIL,
// 还原失败
RESTORE_PROCESS_DO_FAIL,
// 还原成功开始
RESTORE_START_SUCCESS,
// 还原成功,信号未使用此结果
RESTORE_DO_SUCCESS,
// ghost镜像未找到备份点
GHOST_CANNOT_FIND_BACKUPPOINT,
// ghost源目录不存在
GHOST_SRC_DIRECTORY_IS_NOT_EXIST,
// ghost进程启动失败
GHOST_PROCESS_START_FAIL,
// ghost进程启动成功
GHOST_START_SUCCESS,
// 后面的为新版本新增部分
// 根据操作类型动态创建处理类失败
NO_FOUND_DEALCLASS,
};
#endif // MYDEFINE_H

265
common/mylittleparse.cpp Normal file
View File

@ -0,0 +1,265 @@
#include "mylittleparse.h"
#include <QString>
#include <QTextStream>
MyLittleParse::MyLittleParse(const QString& path)
: file(new QFile(path))
, m_e(MyLittleParse::DEFAULT)
{
}
MyLittleParse::~MyLittleParse()
{
file->close();
delete file;
}
bool MyLittleParse::add(const QString& key, const QString& value, MyLittleParse::error_enum& e)
{
QString find_value;
if (find(key, find_value, e)) {
//key=<不空值>
if (!find_value.isEmpty()) {
e = MyLittleParse::KEY_EXITS;
return false;
}
//key=<空值>
return mod(key, value, e);
}
if (!file->open(QIODevice::ReadWrite)) {
e = MyLittleParse::OPEN_FILE_FAIL;
return false;
}
QTextStream out(file);
file->readAll();
out << key << "=" << value << "\n";
file->close();
e = MyLittleParse::SUCCESS;
return true;
}
bool MyLittleParse::add(const QString&& key, const QString&& value)
{
QString _key = key;
QString _value = value;
return add(_key, _value);
}
bool MyLittleParse::Add(const QString &key, const QString &value)
{
MyLittleParse::error_enum e;
bool t = add(key, value, e);
if (!t && e == MyLittleParse::KEY_EXITS) {
t = mod(key, value);
}
return t;
}
bool MyLittleParse::add(const QString& key, const QString& value)
{
return add(key, value, m_e);
}
bool MyLittleParse::del(const QString& key, MyLittleParse::error_enum& e)
{
if (!find_only(key, e)) {
return false;
}
if (!file->open(QIODevice::ReadOnly)) {
e = MyLittleParse::OPEN_FILE_FAIL;
return false;
}
QTextStream out(file);
QString strAll = out.readAll();
file->close();
QStringList strList = strAll.split("\n");
QStringList strDstList;
QString tmp_key;
for (QString& line : strList) {
if (line.trimmed().isEmpty())
continue;
tmp_key = line.section('=', 0, 0).trimmed();
if (tmp_key == key)
continue;
strDstList << line << "\n";
}
file->open(QIODevice::Truncate | QIODevice::WriteOnly);
for (auto s : strDstList)
out << s;
out.flush();
file->close();
e = MyLittleParse::SUCCESS;
return true;
}
bool MyLittleParse::del(const QString&& key)
{
QString _key = key;
return del(_key);
}
bool MyLittleParse::del(const QString& key)
{
return del(key, m_e);
}
bool MyLittleParse::mod(const QString& key, const QString& value, MyLittleParse::error_enum& e)
{
if (!find_only(key, e)) {
return false;
}
if (!file->open(QIODevice::ReadOnly)) {
e = MyLittleParse::OPEN_FILE_FAIL;
return false;
}
QTextStream out(file);
QString strAll = out.readAll();
file->close();
QStringList strList = strAll.split("\n");
QStringList strDstList;
QString tmp_key;
QString tmp_value;
for (QString& line : strList) {
tmp_key = line.section('=', 0, 0).trimmed();
if (tmp_key == key) {
tmp_value = line.section('=', 1, 1).trimmed();
if (tmp_value == value) {
e = MyLittleParse::REPEAT;
file->close();
return false;
}
line.clear();
line = key + "=" + value;
}
strDstList << line << "\n";
}
file->open(QIODevice::Truncate | QIODevice::WriteOnly);
for (auto& s : strDstList)
out << s;
out.flush();
file->close();
e = MyLittleParse::SUCCESS;
return true;
}
bool MyLittleParse::mod(const QString& key, const QString& value)
{
return mod(key, value, m_e);
}
bool MyLittleParse::mod(const QString&& key, const QString&& value)
{
QString _key = key;
QString _value = value;
return mod(_key, _value);
}
bool MyLittleParse::Mod(const QString &key, const QString &value)
{
MyLittleParse::error_enum e;
bool t = mod(key, value, e);
if (!t && e == MyLittleParse::REPEAT) {
return true;
}
return t;
}
bool MyLittleParse::find(const QString& key, QString& value, MyLittleParse::error_enum& e)
{
if (!file->open(QIODevice::ReadOnly)) {
e = MyLittleParse::OPEN_FILE_FAIL;
return false;
}
QTextStream out(file);
QString line;
QString tmp_key;
while (1) {
if (out.atEnd())
break;
line = out.readLine();
if (line.trimmed().isEmpty())
continue;
tmp_key = line.section('=', 0, 0).trimmed();
if (key == tmp_key) {
value = line.section('=', 1, 1).trimmed();
file->close();
e = MyLittleParse::SUCCESS;
return true;
}
}
file->close();
e = MyLittleParse::KEY_NOEXITS;
return false;
}
bool MyLittleParse::find(const QString& key, QString& value)
{
return find(key, value, m_e);
}
bool MyLittleParse::find(const QString&& key, QString&& value)
{
QString _key = key;
QString _value = value;
return find(_key, _value);
}
bool MyLittleParse::find_only(const QString& key, MyLittleParse::error_enum& e)
{
QString value;
if (find(key, value, e))
return true;
return false;
}
bool MyLittleParse::find_only(const QString& key)
{
return find_only(key, m_e);
}
bool MyLittleParse::find_only(const QString&& key)
{
QString _key = key;
return find_only(_key);
}
MyLittleParse::error_enum MyLittleParse::getErrEnum() const
{
return m_e;
}
QString MyLittleParse::getErrMsg()
{
switch (m_e) {
case MyLittleParse::DEFAULT:
return "default";
case MyLittleParse::KEY_EXITS:
return "KEY_EXITS";
case MyLittleParse::OPEN_FILE_FAIL:
return "OPEN_FILE_FAIL";
case MyLittleParse::KEY_NOEXITS:
return "KEY_NOEXITS";
case MyLittleParse::REPEAT:
return "REPEAT";
case MyLittleParse::SUCCESS:
return "SUCCESS";
default:
break;
}
return "";
}

121
common/mylittleparse.h Normal file
View File

@ -0,0 +1,121 @@
#pragma once
#include <QFile>
class QString;
class MyLittleParse {
public:
enum error_enum {
DEFAULT,
OPEN_FILE_FAIL,
KEY_EXITS, //key存在value为空, 适用于add
REPEAT, //key和value都存在且重复适用于mod
KEY_NOEXITS, //不能找到key, 适用于find
SUCCESS
};
MyLittleParse(const QString& path);
~MyLittleParse();
/**
* @brief add
* @param key
* @param value
* @param e
* @return
*
* false e = OPEN_FILE_FAIL
* key不存在, key=value, e = SUCCESS
* key存在= mod
* key存在=false, e = KEY_EXISTS
*
*/
bool add(const QString& key, const QString& value, error_enum& e);
bool add(const QString& key, const QString& value);
bool add(const QString&& key, const QString&& value);
/**
* @brief Add
* @param key
* @param value
* @return
*
* key不存在, key=value
* key存在 mod
*
*/
bool Add(const QString& key, const QString& value);
/**
* @brief del
* @param key
* @param e
* @return
*
* find_onlykey = falsefalse
* false e = OPEN_FILE_FAIL
*
*/
bool del(const QString& key, error_enum& e);
bool del(const QString& key);
bool del(const QString&& key);
/**
* @brief mod
* @param key
* @param value
* @param e
* @return
*
* find_onlykey = falsefalse
* false e = OPEN_FILE_FAIL
* key对应的值和value相等false e = REPEAT
*/
bool mod(const QString& key, const QString& value, error_enum& e);
bool mod(const QString& key, const QString& value);
bool mod(const QString&& key, const QString&& value);
/**
* @brief Mod
* @param key
* @param value
* @return
*
*
* key对应的值和value相等true
*/
bool Mod(const QString& key, const QString& value);
/**
* @brief find
* @param key
* @param value
* @param e
* @return
*
* false e = OPEN_FILE_FAIL
* keyvalue
*/
bool find(const QString& key, QString& value, error_enum& e);
bool find(const QString& key, QString& value);
bool find(const QString&& key, QString&& value);
/**
* @brief find_only
* @param key
* @param e
* @return
* false e = OPEN_FILE_FAIL
*/
bool find_only(const QString& key, error_enum& e);
bool find_only(const QString& key);
bool find_only(const QString&& key);
error_enum getErrEnum() const;
QString getErrMsg();
private:
QFile* file;
error_enum m_e;
};

49
common/reflect.cpp Normal file
View File

@ -0,0 +1,49 @@
/**
* brief
* author
* note :
* 1QObject或其派生数的上层节点包含QObject
* 2
* 3使DECLARE_DYNAMIC_CLASS(yourClassName); .cpp使IMPL_DYNAMIC_CLASS(yourClassName)
* 4
* .h中
* #include <QObject>
* #include "../common/reflect.h"
* class MyClass : public QObject
* {
* Q_OBJECT
* DECLARE_DYNCREATE(MyClass)
* }
*
* .cpp文件中
* IMPLEMENT_DYNCREATE(MyClass)
*/
#include "reflect.h"
int Reflect::registerClass(const QString& className, Constructor constructor)
{
QHash<QString, Constructor>& instances = constructors();
instances.insert(className, constructor);
return instances.size();
}
QObject * Reflect::createObject(const QString& className)
{
QHash<QString, Constructor>& instances = constructors();
if (instances.contains(className)) {
Constructor constructor = instances[className];
if (constructor != nullptr) {
return (*constructor)();
}
}
return nullptr;
}
QHash<QString, Constructor>& Reflect::constructors()
{
static QHash<QString, Constructor> _instances;
return _instances;
}

55
common/reflect.h Normal file
View File

@ -0,0 +1,55 @@
/**
* brief
* author
* note :
* 1QObject或其派生数的上层节点包含QObject
* 2
* 3使DECLARE_DYNAMIC_CLASS(yourClassName); .cpp使IMPL_DYNAMIC_CLASS(yourClassName)
* 4
* .h中
* #include <QObject>
* #include "../common/reflect.h"
* class MyClass : public QObject
* {
* Q_OBJECT
* DECLARE_DYNCREATE(MyClass)
* }
*
* .cpp文件中
* IMPLEMENT_DYNCREATE(MyClass)
*/
#ifndef REFLECT_H
#define REFLECT_H
#include <QObject>
#include <QHash>
#include <QString>
typedef QObject * (*Constructor)();
class Reflect
{
public:
static int registerClass(const QString& className, Constructor constructor);
static QObject * createObject(const QString& className);
private:
static QHash<QString, Constructor>& constructors();
};
#define DECLARE_DYNCREATE(class_name) \
public: \
static QObject * create##class_name##Object();
#define IMPLEMENT_DYNCREATE(class_name) \
QObject * class_name::create##class_name##Object() \
{ \
return (QObject *)(new class_name()); \
} \
static int g_icreate##class_name##Object = Reflect::registerClass(#class_name, class_name::create##class_name##Object);
#endif //!REFLECT_H

36
common/singleton.h Normal file
View File

@ -0,0 +1,36 @@
/**
* brief 1.使
* 2.Singleton模板的默认构造函数是受保护的protected
* 3.token类型的参数
* author
* note 使
class MysqlPool :public Singleton<MysqlPool> {
public:
MysqlPool(token) {};
~MysqlPool();
...
};
*/
#ifndef SINGLETON_H_
#define SINGLETON_H_
template <class T>
class Singleton
{
public:
Singleton(const Singleton&) = delete;
Singleton& operator= (const Singleton) = delete;
public:
static auto& inst() {
static T _{ token{} };
return _;
}
protected:
struct token {};
Singleton() = default;
};
#endif

36
common/spinlock_mutex.h Normal file
View File

@ -0,0 +1,36 @@
/**
* @author
* @note c++11, std::shared_lock<spinlock_mutex>std::lock_guard<spinlock_mutex>
*/
#pragma once
#ifndef __SPINLOCK_MUTEX_H__
#define __SPINLOCK_MUTEX_H__
#include <atomic>
class spinlock_mutex
{
std::atomic_flag flag = ATOMIC_FLAG_INIT; //注意:不能用初始化列表初始化,拷贝构造和复制构造函数已经删除
public:
spinlock_mutex() {}
void lock()
{
while (flag.test_and_set(std::memory_order_acquire));
}
void unlock()
{
flag.clear(std::memory_order_release);
}
bool try_lock()
{
return !flag.test_and_set(std::memory_order_acquire);
}
};
#endif //!__SPINLOCK_MUTEX_H__

304
common/utils.cpp Normal file
View File

@ -0,0 +1,304 @@
#include "utils.h"
#include <QByteArray>
#include <QDateTime>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QRegularExpression>
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "mylittleparse.h"
QString Utils::m_sysRootPath = "/";
/**
* @brief initSysRootPath,
* @param qsAppPath
* @note
* /usr/bin中
* 1. grub引导中根目录为/root
* 2. livecd中根目录为/target
* 3. 使/
*/
void Utils::initSysRootPath(const QString& qsAppPath)
{
QString sysRootPath = qsAppPath;
if (sysRootPath.contains(DEFAULT_APP_PATH)) {
sysRootPath.replace(DEFAULT_APP_PATH, "/");
} else {
sysRootPath = "/";
}
m_sysRootPath = sysRootPath;
}
/**
* @brief customMessageHandler
* @param type debug等
* @param context
* @param msg
*/
void Utils::customMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
QByteArray localMsg = msg.toLocal8Bit();
QString strMsg("");
switch (type) {
case QtDebugMsg:
strMsg = QString("[Debug]");
break;
case QtWarningMsg:
strMsg = QString("[Warning]");
break;
case QtCriticalMsg:
strMsg = QString("[Critical]");
break;
case QtFatalMsg:
strMsg = QString("[Fatal]");
break;
default:
strMsg = QString("[Debug]");
break;
}
// 设置输出信息格式
QString strDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
QString strMessage = strMsg + QString("DateTime:%1 Message:%2 File:%3(%4)")
.arg(strDateTime).arg(localMsg.constData()).arg(context.file).arg(context.line);
std::cout << strMessage.toUtf8().data() << std::endl;
// 输出信息至文件中(读写、追加形式)
QString fileName = m_sysRootPath + "/var/log/backup.log";
fileName.replace("//", "/");
QFile file(fileName);
file.open(QIODevice::ReadWrite | QIODevice::Append);
QTextStream stream(&file);
stream << strMessage << endl;
file.flush();
file.close();
}
/**
* @brief
* @param frontUidid
* @return
* @note 使QLockFile
* /tmp/lock路径下的锁文件xx程序在运行不允许关机等
*/
int Utils::lockProgram(int frontUid)
{
QDir dir("/tmp/lock");
if (!dir.exists()) {
dir.mkdir("/tmp/lock");
chmod("/tmp/lock", S_IRWXU | S_IRWXG | S_IRWXO);
}
int lock_file_fd = ::open(LOCK_FILE, O_CREAT | O_RDWR, 0666);
if (0 > lock_file_fd) {
return -2;
}
fchmod(lock_file_fd, S_IRWXU | S_IRWXG | S_IRWXO);
int lock_ret = flock(lock_file_fd, LOCK_EX | LOCK_NB);
if (0 > lock_ret) {
return -11;
}
ftruncate(lock_file_fd, 0);
char write_string[PID_STRING_LEN] = { 0 };
snprintf(write_string, PID_STRING_LEN, "%d\n%s\n", frontUid, BACKUP_CLI_NAME);
write(lock_file_fd, write_string, strlen(write_string));
fdatasync(lock_file_fd);
return lock_file_fd;
}
/**
* @brief
* @param lock_file_fd
* @return 01
*/
int Utils::unLockProgram(int lock_file_fd)
{
int lock_ret = flock(lock_file_fd, LOCK_UN);
if (lock_ret < 0) {
qCritical("unlock fail!");
return 1;
}
qDebug("unlock success!");
rmLockFile();
return 0;
}
/**
* @brief
* @return bool
*/
bool Utils::rmLockFile()
{
bool res = QFile::remove(LOCK_FILE);
if (!res)
qCritical() << QString("remove %s fail").arg(LOCK_FILE);
return res;
}
/**
* @brief /etc/.bootinfo是否存在并可读UUID等信息
* @return bool
*/
bool Utils::checkBootInfoExists()
{
QString bootinfoPath = Utils::m_sysRootPath + BOOTINFO_PATH;
bootinfoPath.replace("//", "/");
QFile bootinfoFile(bootinfoPath);
if (!bootinfoFile.exists()) {
qCritical("%s is not exists!", qUtf8Printable(bootinfoPath));
return false;
}
if (!bootinfoFile.open(QIODevice::ReadOnly)) {
qCritical("%s file can't open!", qUtf8Printable(bootinfoPath));
return false;
}
bootinfoFile.close();
return true;
}
/**
* @brief UUID
* @return
*/
QString Utils::getBackupPartitionUuid()
{
QString bootinfoPath = Utils::m_sysRootPath + BOOTINFO_PATH;
bootinfoPath.replace("//", "/");
MyLittleParse parse(bootinfoPath);
QString restoreUuid;
parse.find("RECOVERY_DEV_UUID", restoreUuid);
return restoreUuid;
}
/**
* @brief
* @param path
*/
void Utils::mkdir(const QString& path)
{
QDir dir(path);
if (!dir.exists())
dir.mkdir(path);
}
/**
* @brief
* @param path
* @return bool
*/
bool Utils::mkpath(const QString& path)
{
QDir dir(path);
if (!dir.exists()) {
return dir.mkpath(path);
}
return true;
}
/**
* @brief
* @param excludes
*/
void Utils::excludeFstabBindPath(QStringList &excludes)
{
QString fstabPath = Utils::m_sysRootPath + FSTAB_PATH;
fstabPath.replace("//", "/");
QFile file(fstabPath);
if (!file.open(QIODevice::ReadOnly))
return;
QTextStream in(&file);
while (!in.atEnd()) {
const QString &line = in.readLine();
if (line.startsWith("#"))
continue ;
if (line.startsWith("UUID="))
continue ;
if (line.isEmpty())
continue ;
if (!line.contains("bind"))
continue ;
// 配置文件/etc/fstab每行6个域: <file system> <mount point> <type> <options> <dump> <pass>, 形如:
// UUID=232f5fb4-53e0-46b9-ba9b-22bfec64f2a2 /boot ext4 rw,relatime 0 0
QStringList list = line.split(QRegularExpression("[ \t]"));
QStringList fields;
for (int i = 0; i < list.size(); ++i) {
QString field = list.at(i);
field = field.trimmed();
if (field.isEmpty())
continue;
fields << field;
}
// 配置文件/etc/fstab每行6个域第二个域为挂载路径
if (6 == fields.size())
excludes << fields.at(1);
}
file.close();
}
/**
* @brief rsync --exclude路径规则文件
* @return
*/
bool Utils::generateExcludePathsFile()
{
QString excludeFile = Utils::m_sysRootPath + EXCLUDE_FILE_PATH;
excludeFile.replace("//", "/");
QFile excludePathFile(excludeFile);
// 暂时改为每次都重写文件内容,以便能随版本更新排除路径
if (!excludePathFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qCritical("%s create failed", qUtf8Printable(excludeFile));
return false;
}
QTextStream in(&excludePathFile);
in << "/backup" << endl; //分区
in << "/boot/efi" << endl;
// efi原始目录在/boot/efi备份到目标目录为/efi下再还原时已经单独处理了批量还原时应该屏蔽此目录
in << "/efi" << endl;
in << "/dev/*" << endl;
in << "/ghost" << endl; //ghost镜像文件
in << "/mnt/*" << endl;
in << "/proc/*" << endl;
in << "/run/*" << endl;
in << "/sys/*" << endl; //添加*,表示如果/sys目录不存在则会拷贝/sys但不会拷贝/sys下的内容
in << "/media/*" << endl;
in << "/tmp/*" << endl;
in << "/lost+found/*" << endl;
in << "/var/lib/udisks2/*" << endl;
in << "/cdrom/*" << endl;
in << "/swap_file" << endl;
// 安全模块会将文件/usr/share/kysec-utils/data/readonly_list中的文件列表限制只读无法修改、备份包含扩展属性时、删除等
// 现在里面仅有/etc/uid_list先暂时排除掉等后续安全模块有其它保护方案后再进一步修改
in << "/etc/uid_list" << endl;
// 安卓兼容的这个里面很多文件都是设置了特殊扩展文件属性lsetxattr无法设置成功听取安卓兼容模块同事的意见不用管这个文件夹其实是从home下挂载的
in << "/var/lib/kmre" << endl;
in << "/var/log" << endl;
// 系统安装后有的会将/data/home /data/root挂载到的/home /root上实际文件是存放在/data/home /data/root下面
QStringList excludes;
Utils::excludeFstabBindPath(excludes);
for (const QString& item : excludes) {
in << item << endl;
}
in.flush();
excludePathFile.close();
return true;
}

100
common/utils.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef UTILS_H
#define UTILS_H
#include <QString>
#include <QtDebug>
#include "mydefine.h"
/**
* @brief
* @author zhaominyong
* @since 2021/07/22
*/
class Utils
{
public:
/**
* @brief initSysRootPath,
* @param qsAppPath
*/
static void initSysRootPath(const QString& qsAppPath);
/**
* @brief getSysRootPath
* @return const QString&
* @note
* initSysRootPath/
*/
static const QString& getSysRootPath() { return m_sysRootPath; }
/**
* @brief customMessageHandler
* @param type debug等
* @param context
* @param msg
*/
static void customMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
/**
* @brief
* @param frontUidid
* @return
*/
static int lockProgram(int frontUid);
/**
* @brief
* @param lock_file_fd
* @return 01
*/
static int unLockProgram(int lock_file_fd);
/**
* @brief
* @return bool
*/
static bool rmLockFile();
/**
* @brief /etc/.bootinfo是否存在并可读UUID等信息
* @return bool
*/
static bool checkBootInfoExists();
/**
* @brief UUID
* @return UUID
*/
static QString getBackupPartitionUuid();
/**
* @brief
* @param path
*/
static void mkdir(const QString& path);
/**
* @brief
* @param path
* @return bool
*/
static bool mkpath(const QString& path);
/**
* @brief
* @param excludes
*/
static void excludeFstabBindPath(QStringList &excludes);
/**
* @brief rsync --exclude路径规则文件
* @return
*/
static bool generateExcludePathsFile();
private:
// 系统根目录,默认"/"
static QString m_sysRootPath;
};
#endif // UTILS_H

View File

@ -0,0 +1,26 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.backup.manager.xml -p ComKylinBackupManagerInterface
*
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* This is an auto-generated file.
* This file may have been hand-edited. Look for HAND-EDIT comments
* before re-generating it.
*/
#include "backup_manager_interface.h"
/*
* Implementation of interface class ComKylinBackupManagerInterface
*/
ComKylinBackupManagerInterface::ComKylinBackupManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)
: QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)
{
}
ComKylinBackupManagerInterface::~ComKylinBackupManagerInterface()
{
}

View File

@ -0,0 +1,140 @@
/*
* This file was generated by qdbusxml2cpp version 0.8
* Command line was: qdbusxml2cpp com.kylin.backup.manager.xml -p ComKylinBackupManagerInterface
*
* qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd.
*
* This is an auto-generated file.
* Do not edit! All changes made to it will be lost.
*/
#ifndef COMKYLINBACKUPMANAGERINTERFACE_H
#define COMKYLINBACKUPMANAGERINTERFACE_H
#include <QtCore/QObject>
#include <QtCore/QByteArray>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtDBus/QtDBus>
#include "../common/mydefine.h"
/*
* Proxy class for interface com.kylin.backup.manager
*/
class ComKylinBackupManagerInterface: public QDBusAbstractInterface
{
Q_OBJECT
public:
static inline const char *staticInterfaceName()
{ return "com.kylin.backup.manager"; }
public:
ComKylinBackupManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);
~ComKylinBackupManagerInterface();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<int> Mount_backup_partition()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("Mount_backup_partition"), argumentList);
}
inline QDBusPendingReply<> autoBackUpForSystemUpdate_noreturn(const QString &autobackup_name, const QString &create_note, const QString &inc_note, const QString &frontUserName, int frontUid)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(autobackup_name) << QVariant::fromValue(create_note) << QVariant::fromValue(inc_note) << QVariant::fromValue(frontUserName) << QVariant::fromValue(frontUid);
return asyncCallWithArgumentList(QStringLiteral("autoBackUpForSystemUpdate_noreturn"), argumentList);
}
inline QDBusPendingReply<int> checkEnv(BackupWrapper backupWrapper)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backupWrapper);
return asyncCallWithArgumentList(QStringLiteral("checkEnv"), argumentList);
}
inline QDBusPendingReply<int> deleteBackupPoint(BackupWrapper backupWrapper)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backupWrapper);
return asyncCallWithArgumentList(QStringLiteral("deleteBackupPoint"), argumentList);
}
inline QDBusPendingReply<QString, QString> getBackupCommentForSystemUpdate()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("getBackupCommentForSystemUpdate"), argumentList);
}
inline QDBusReply<QString> getBackupCommentForSystemUpdate(QString &state)
{
QList<QVariant> argumentList;
QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("getBackupCommentForSystemUpdate"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
state = qdbus_cast<QString>(reply.arguments().at(1));
}
return reply;
}
inline QDBusPendingReply<int, bool> getBackupState()
{
QList<QVariant> argumentList;
return asyncCallWithArgumentList(QStringLiteral("getBackupState"), argumentList);
}
inline QDBusReply<int> getBackupState(bool &isActive)
{
QList<QVariant> argumentList;
QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("getBackupState"), argumentList);
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) {
isActive = qdbus_cast<bool>(reply.arguments().at(1));
}
return reply;
}
inline QDBusPendingReply<int> ghostBackup(BackupWrapper backupWrapper)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backupWrapper);
return asyncCallWithArgumentList(QStringLiteral("ghostBackup"), argumentList);
}
inline QDBusPendingReply<int> goBackup(BackupWrapper backupWrapper)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backupWrapper);
return asyncCallWithArgumentList(QStringLiteral("goBackup"), argumentList);
}
inline QDBusPendingReply<int> goRestore(BackupWrapper backupWrapper)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(backupWrapper);
return asyncCallWithArgumentList(QStringLiteral("goRestore"), argumentList);
}
inline QDBusPendingReply<> cancel()
{
return asyncCall(QStringLiteral("cancel"));
}
Q_SIGNALS: // SIGNALS
void sendBackupResult(bool result);
void sendDeleteResult(bool result);
void sendEnvCheckResult(int result);
void sendGhostBackupResult(bool result);
void sendRate(int in0, int in1);
void sendRestoreResult(bool result);
void sendStartBackupResult(int result);
};
namespace com {
namespace kylin {
namespace backup {
typedef ::ComKylinBackupManagerInterface manager;
}
}
}
#endif

34
kybackup/kybackup.pro Normal file
View File

@ -0,0 +1,34 @@
QT += core gui
QT += dbus
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# 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
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
HEADERS += \
backup_manager_interface.h \
maindialog.h
SOURCES += \
backup_manager_interface.cpp \
main.cpp \
maindialog.cpp
FORMS += \
maindialog.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

11
kybackup/main.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "maindialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainDialog w;
w.show();
return a.exec();
}

15
kybackup/maindialog.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "maindialog.h"
#include "ui_maindialog.h"
MainDialog::MainDialog(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainDialog)
{
ui->setupUi(this);
}
MainDialog::~MainDialog()
{
delete ui;
}

21
kybackup/maindialog.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef MAINDIALOG_H
#define MAINDIALOG_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainDialog; }
QT_END_NAMESPACE
class MainDialog : public QMainWindow
{
Q_OBJECT
public:
MainDialog(QWidget *parent = nullptr);
~MainDialog();
private:
Ui::MainDialog *ui;
};
#endif // MAINDIALOG_H

22
kybackup/maindialog.ui Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainDialog</class>
<widget class="QMainWindow" name="MainDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainDialog</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar"/>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

8
yhkylin-backup-tool.pro Normal file
View File

@ -0,0 +1,8 @@
TEMPLATE = subdirs
SUBDIRS += \
kybackup \
backup-daemon
CONFIG += ordered

View File

@ -0,0 +1,293 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.0, 2021-07-30T14:54:05. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{d6d3c1b3-be59-4e12-87de-c60657210d67}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">桌面</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">桌面</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{5440484b-1916-43f8-99de-3fbc4fe13c66}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/zhaominyong/workspace/kylin-backup-tools-new/build-yhkylin-backup-tool-unknown-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
<value type="bool" key="Qt4ProjectManager.MakeStep.OverrideMakeflags">false</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
<value type="QString">cpu-cycles</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="int" key="Analyzer.Perf.Frequency">250</value>
<valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
<value type="QString">-e</value>
<value type="QString">cpu-cycles</value>
<value type="QString">--call-graph</value>
<value type="QString">dwarf,4096</value>
<value type="QString">-F</value>
<value type="QString">250</value>
</valuelist>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/zhaominyong/workspace/kylin-backup-tools-new/yhkylin-backup-tool/backup-daemon/backup-daemon.pro</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/zhaominyong/workspace/kylin-backup-tools-new/yhkylin-backup-tool/backup-daemon/backup-daemon.pro</value>
<value type="QString" key="RunConfiguration.Arguments"></value>
<value type="bool" key="RunConfiguration.Arguments.multi">false</value>
<value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/zhaominyong/workspace/kylin-backup-tools-new/build-yhkylin-backup-tool-unknown-Debug/backup-daemon</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
<value type="QString">cpu-cycles</value>
</valuelist>
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
<value type="int" key="Analyzer.Perf.Frequency">250</value>
<valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
<value type="QString">-e</value>
<value type="QString">cpu-cycles</value>
<value type="QString">--call-graph</value>
<value type="QString">dwarf,4096</value>
<value type="QString">-F</value>
<value type="QString">250</value>
</valuelist>
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/zhaominyong/workspace/kylin-backup-tools-new/yhkylin-backup-tool/kybackup/kybackup.pro</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/zhaominyong/workspace/kylin-backup-tools-new/yhkylin-backup-tool/kybackup/kybackup.pro</value>
<value type="QString" key="RunConfiguration.Arguments"></value>
<value type="bool" key="RunConfiguration.Arguments.multi">false</value>
<value type="QString" key="RunConfiguration.OverrideDebuggerStartup"></value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseTerminal">false</value>
<value type="QString" key="RunConfiguration.WorkingDirectory"></value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/zhaominyong/workspace/kylin-backup-tools-new/build-yhkylin-backup-tool-unknown-Debug/kybackup</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">22</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>