去掉备份分区依赖
This commit is contained in:
parent
16327ed35e
commit
63b47630e1
|
@ -31,6 +31,7 @@ HEADERS += \
|
|||
../common/spinlock_mutex.h \
|
||||
../common/utils.h \
|
||||
backupmanager_adaptor.h \
|
||||
customizesystembackupproxy.h \
|
||||
databackupproxy.h \
|
||||
datarestoreproxy.h \
|
||||
deletebackupproxy.h \
|
||||
|
@ -59,6 +60,7 @@ SOURCES += \
|
|||
../common/reflect.cpp \
|
||||
../common/utils.cpp \
|
||||
backupmanager_adaptor.cpp \
|
||||
customizesystembackupproxy.cpp \
|
||||
databackupproxy.cpp \
|
||||
datarestoreproxy.cpp \
|
||||
deletebackupproxy.cpp \
|
||||
|
|
|
@ -0,0 +1,556 @@
|
|||
#include "customizesystembackupproxy.h"
|
||||
|
||||
#include <QStorageInfo>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <kysec/status.h>
|
||||
#include "../common/utils.h"
|
||||
#include "../common/mydusizetool.h"
|
||||
#include "mymountproxy.h"
|
||||
|
||||
IMPLEMENT_DYNCREATE(CustomizeSystemBackupProxy)
|
||||
|
||||
CustomizeSystemBackupProxy::CustomizeSystemBackupProxy()
|
||||
{
|
||||
m_bSuccess = false;
|
||||
m_isFinished = false;
|
||||
m_size = 0;
|
||||
m_calc = new CalcBackupSize(this);
|
||||
m_isOnlyCheck = true;
|
||||
m_mksquashfs = nullptr;
|
||||
m_isForce = false;
|
||||
|
||||
connect(this, &CustomizeSystemBackupProxy::cancel, this, &CustomizeSystemBackupProxy::cancelEx);
|
||||
}
|
||||
|
||||
CustomizeSystemBackupProxy::~CustomizeSystemBackupProxy()
|
||||
{
|
||||
delete m_calc;
|
||||
m_calc = nullptr;
|
||||
|
||||
delete m_mksquashfs;
|
||||
m_mksquashfs = nullptr;
|
||||
|
||||
QString rm("rm -rf ");
|
||||
rm += m_imgPath;
|
||||
QProcess::execute(rm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 环境检测
|
||||
* @return
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::checkEnvEx()
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::checkEnv invoke begin";
|
||||
|
||||
// 1、检查/backup分区是否挂载上(不管是本地磁盘还是u盘设备,都得保证/backup挂载上); 若没挂载,挂载
|
||||
MyMountProxy mountProxy;
|
||||
if ( MountResult::MOUNTED != mountProxy.mountBackupPartition() ) {
|
||||
emit checkResult(int(BackupResult::BACKUP_PARTITION_MOUNT_FAIL));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString backupPath(m_backupWrapper.m_prefixDestPath);
|
||||
backupPath.replace("//", "/");
|
||||
QStorageInfo udisk(backupPath);
|
||||
QString udisk_type = udisk.fileSystemType();
|
||||
if (udisk_type == "vfat") {
|
||||
qCritical() << m_backupWrapper.m_prefixDestPath + " udisk's filesystemtype is vfat";
|
||||
emit checkResult(int(BackupResult::UDISK_FILESYSTEM_TYPE_IS_VFAT));
|
||||
return false;
|
||||
}
|
||||
if (udisk.isReadOnly()) {
|
||||
// 只读挂载的U盘
|
||||
qCritical() << QString("udisk(%s) is readonly filesystem").arg(m_backupWrapper.m_prefixDestPath);
|
||||
emit checkResult(int(BackupResult::UDISK_FILESYSTEM_IS_READONLY));
|
||||
return false;
|
||||
}
|
||||
|
||||
QTimer::singleShot(1*1000, this, &CustomizeSystemBackupProxy::checkDestDirExists);
|
||||
// 2、计算备份大小
|
||||
calcSizeForBackup();
|
||||
|
||||
qDebug() << "CustomizeSystemBackupProxy::checkEnv invoke end";
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行备份逻辑
|
||||
*/
|
||||
void CustomizeSystemBackupProxy::doWorkEx()
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::doWorkEx invoke begin";
|
||||
|
||||
m_isOnlyCheck = false;
|
||||
// 环境检测
|
||||
checkEnvEx();
|
||||
|
||||
qDebug() << "CustomizeSystemBackupProxy::doWorkEx invoke end";
|
||||
}
|
||||
|
||||
void CustomizeSystemBackupProxy::cancelEx()
|
||||
{
|
||||
m_bCancel = true;
|
||||
if (!m_isFinished) {
|
||||
emit this->checkResult(int(BackupResult::START_CANCEL));
|
||||
|
||||
if (m_calc)
|
||||
m_calc->stop();
|
||||
if (m_mksquashfs)
|
||||
m_mksquashfs->stop();
|
||||
|
||||
QProcess::execute("sync");
|
||||
Utils::wait(5);
|
||||
deleteFailedData();
|
||||
emit this->checkResult(int(BackupResult::CANCEL_SUCCESS));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 失败则删除相应数据
|
||||
*/
|
||||
void CustomizeSystemBackupProxy::deleteFailedData()
|
||||
{
|
||||
if (m_curUuid.isEmpty())
|
||||
return;
|
||||
|
||||
// 1、删除备份目录
|
||||
QString destPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid;
|
||||
destPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-rf";
|
||||
args << destPath;
|
||||
QProcess::execute("rm", args);
|
||||
|
||||
// 2、删除xml文件中的备份项
|
||||
QString xmlPath = m_backupWrapper.m_prefixDestPath + BACKUP_XML_PATH;
|
||||
xmlPath.replace("//", "/");
|
||||
ParseBackupList parse(xmlPath);
|
||||
parse.deleteItem(m_curUuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 判断是否增量备份
|
||||
* @return true,增量备份; false,全量备份
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::isIncBackup()
|
||||
{
|
||||
QString backupPath;
|
||||
ParseBackupList::BackupPoint point;
|
||||
if (m_backupWrapper.m_uuid.isEmpty()) {
|
||||
QString xmlPath(m_backupWrapper.m_prefixDestPath + BACKUP_XML_PATH);
|
||||
xmlPath.replace("//", "/");
|
||||
ParseBackupList parser(xmlPath);
|
||||
point = parser.getLastSysBackupPoint();
|
||||
if (point.m_uuid.isEmpty())
|
||||
return false;
|
||||
backupPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + point.m_uuid + "/data";
|
||||
} else {
|
||||
backupPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
|
||||
}
|
||||
|
||||
backupPath.replace("//", "/");
|
||||
if (Utils::isDirExist(backupPath)) {
|
||||
m_backupWrapper.m_baseUuid = point.m_uuid;
|
||||
m_backupWrapper.m_bIncrement = true;
|
||||
m_backupWrapper.m_type = BackupType::INC_BACKUP_SYSTEM;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 校验剩余空间是否满足备份
|
||||
*/
|
||||
void CustomizeSystemBackupProxy::checkFreeCapacity(qint64 itotalSize)
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::checkFreeCapacity invoke begin";
|
||||
|
||||
// 如果是取消了操作,则不再发送其它信息
|
||||
if (m_bCancel)
|
||||
return ;
|
||||
|
||||
// 拔掉U盘的场景
|
||||
if (m_isForce) {
|
||||
emit this->checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
|
||||
return ;
|
||||
}
|
||||
|
||||
// 1、计算待备份数据的大小
|
||||
m_size = itotalSize;
|
||||
// 备份过程中会有一些临时文件产生,会占用一部分空间,故我们预留500M的空间
|
||||
itotalSize += 500 * MB;
|
||||
|
||||
// 2、计算备份分区剩余空间大小
|
||||
QString backupPath(m_backupWrapper.m_prefixDestPath);
|
||||
backupPath.replace("//", "/");
|
||||
QStorageInfo backupDisk(backupPath);
|
||||
qint64 freeSize = backupDisk.bytesAvailable();
|
||||
|
||||
// 3、校验空间是否足够
|
||||
if (itotalSize > freeSize) {
|
||||
emit checkResult(int(BackupResult::BACKUP_CAPACITY_IS_NOT_ENOUGH));
|
||||
} else {
|
||||
emit checkResult(int(BackupResult::CHECK_ENV_SUCCESS));
|
||||
}
|
||||
|
||||
if (m_isOnlyCheck)
|
||||
return ;
|
||||
|
||||
// 4、判断是否需要先压缩成img文件,压缩后一般小于原大小的70%
|
||||
itotalSize = itotalSize * 7 / 10;
|
||||
QHash<QString, QString> hash = Utils::getLeftSizeOfPartitions();
|
||||
for (QHash<QString, QString>::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it) {
|
||||
QString path = it.key();
|
||||
QString size = it.value();
|
||||
if (size.endsWith("G")) {
|
||||
size.replace("G", "");
|
||||
qint64 leftSize = size.toLongLong() * 1000 * 1000 * 1000;
|
||||
if (itotalSize < leftSize) {
|
||||
m_imgPath = path + IMGBACKUP_PATH;
|
||||
m_imgPath.replace("//", "/");
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5、开始制作img或开始备份
|
||||
if (m_imgPath.isEmpty()) {
|
||||
doBackup();
|
||||
} else {
|
||||
doMksqushfs();
|
||||
}
|
||||
|
||||
qDebug() << "CustomizeSystemBackupProxy::checkFreeCapacity invoke end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算备份所需空间大小
|
||||
* @return 计算备份所需空间大小,单位字节
|
||||
*/
|
||||
void CustomizeSystemBackupProxy::calcSizeForBackup()
|
||||
{
|
||||
// 拼接备份源路径和目标路径,测试所需备份空间大小;目标路径为一虚拟路径
|
||||
QString srcPath = Utils::getSysRootPath();
|
||||
srcPath += "/";
|
||||
srcPath.replace("//", "/");
|
||||
QString destPath = Utils::getSysRootPath();
|
||||
destPath += CHECK_PATH;
|
||||
destPath.replace("//", "/");
|
||||
Utils::mkpath(destPath);
|
||||
|
||||
QStringList args = getRsyncArgs(CustomizeSystemBackupScene::TRY_SYSTEM_BACKUP);
|
||||
args << srcPath;
|
||||
args << destPath;
|
||||
|
||||
connect(m_calc, &CalcBackupSize::finished, this, &CustomizeSystemBackupProxy::checkFreeCapacity);
|
||||
m_calc->start(args, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 根据场景获取rsync命令参数
|
||||
* @param scene,场景
|
||||
* @return rsync的参数信息
|
||||
*/
|
||||
QStringList CustomizeSystemBackupProxy::getRsyncArgs(CustomizeSystemBackupScene scene)
|
||||
{
|
||||
QStringList args;
|
||||
QStringList excludes;
|
||||
|
||||
switch (scene) {
|
||||
case CustomizeSystemBackupScene::SYSTEM_BACKUP :
|
||||
args << "-avAHXr";
|
||||
args << "--info=progress2";
|
||||
args << "--no-inc-recursive";
|
||||
args << "--ignore-missing-args";
|
||||
break ;
|
||||
case CustomizeSystemBackupScene::TRY_SYSTEM_BACKUP :
|
||||
args << "-aAHXrn";
|
||||
args << "--stats";
|
||||
args << "--ignore-missing-args";
|
||||
break ;
|
||||
case CustomizeSystemBackupScene::MKSQUASHFS :
|
||||
Utils::excludeFstabBindPath(excludes);
|
||||
// --exclude=排除路径设置
|
||||
for (QString item : m_backupWrapper.m_backupExcludePaths) {
|
||||
if (excludes.contains(item))
|
||||
continue;
|
||||
if (item.endsWith("/*")) {
|
||||
item.replace("/*", "");
|
||||
}
|
||||
|
||||
args << "-e" << item;
|
||||
}
|
||||
args << "-e" << m_imgPath;
|
||||
return args;
|
||||
default:
|
||||
return args;
|
||||
}
|
||||
|
||||
// --exclude=排除路径设置
|
||||
for (const QString & item : m_backupWrapper.m_backupExcludePaths) {
|
||||
args << QString("--exclude=%1").arg(item);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mksqushfs
|
||||
*/
|
||||
void CustomizeSystemBackupProxy::doMksqushfs()
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::doMksqushfs invoke begin";
|
||||
|
||||
m_mksquashfs = new MkSquashFSProcess(this);
|
||||
connect(m_mksquashfs, &MkSquashFSProcess::progress, this, &CustomizeSystemBackupProxy::progress);
|
||||
connect(m_mksquashfs, &MkSquashFSProcess::finished, this, [=](bool result) {
|
||||
// 如果是取消了操作,则不再发送其它信息
|
||||
if (m_bCancel)
|
||||
return ;
|
||||
|
||||
if (result && !m_isForce) {
|
||||
// 开始备份
|
||||
doBackup();
|
||||
} else {
|
||||
m_isFinished = true;
|
||||
emit checkResult(int(BackupResult::MKSQUASHFS_DO_FAIL));
|
||||
}
|
||||
});
|
||||
Utils::mkpath(m_imgPath);
|
||||
|
||||
QString srcPath = Utils::getSysRootPath();
|
||||
srcPath += "/";
|
||||
srcPath.replace("//", "/");
|
||||
QString dstImg = m_imgPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
|
||||
QStringList args;
|
||||
args << srcPath << dstImg;
|
||||
args.append(getRsyncArgs(CustomizeSystemBackupScene::MKSQUASHFS));
|
||||
|
||||
if (m_mksquashfs->start(args)) {
|
||||
emit checkResult(int(BackupResult::MKSQUASHFS_START_SUCCESS));
|
||||
} else {
|
||||
emit checkResult(int(BackupResult::MKSQUASHFS_DO_FAIL));
|
||||
}
|
||||
|
||||
qDebug() << "CustomizeSystemBackupProxy::doMksqushfs invoke end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 备份
|
||||
*/
|
||||
void CustomizeSystemBackupProxy::doBackup()
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::doBackup invoke begin";
|
||||
|
||||
// 准备
|
||||
if (!doPrepare())
|
||||
return ;
|
||||
|
||||
// 启动备份efi, 修改为和其它目录统一备份,不再单独进行备份
|
||||
// if (!backupEfi()) {
|
||||
// emit checkResult(int(BackupResult::EFI_RSYNC_FAIL));
|
||||
// return ;
|
||||
// }
|
||||
|
||||
if (m_imgPath.isEmpty()) {
|
||||
// 启动系统备份
|
||||
backupSystem();
|
||||
} else {
|
||||
// 备份img文件
|
||||
backupImg();
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "CustomizeSystemBackupProxy::doBackup invoke end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 备份准备
|
||||
* @return true,准备成功;false,准备失败
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::doPrepare()
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::doPrepare invoke begin";
|
||||
|
||||
m_bSuccess = false;
|
||||
|
||||
// 1、设置当前备份的Uuid
|
||||
m_curUuid += Utils::createUuid();
|
||||
|
||||
// 2、准备备份目录及文件
|
||||
m_destPath = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/data";
|
||||
m_destPath.replace("//", "/");
|
||||
if (!Utils::mkpath(m_destPath)) {
|
||||
qCritical() << QString("mkdir %1 failed !").arg(m_destPath) ;
|
||||
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString userFile = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + PATHS_USER_FILE;
|
||||
userFile.replace("//", "/");
|
||||
if (!Utils::writeFileByLines(userFile, m_backupWrapper.m_backupPaths)) {
|
||||
qCritical() << QString("create file %1 failed !").arg(userFile);
|
||||
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString excludeUserFile = m_backupWrapper.m_prefixDestPath + BACKUP_SNAPSHOTS_PATH + "/" + m_curUuid + "/" + EXCLUDE_PATHS_USER_FILE;
|
||||
excludeUserFile.replace("//", "/");
|
||||
if (!Utils::writeFileByLines(excludeUserFile, m_backupWrapper.m_backupExcludePaths)) {
|
||||
qCritical() << QString("create file %1 failed !").arg(excludeUserFile);
|
||||
emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3、记录/backup/snapshots/backuplist.xml文件
|
||||
if (!recordBackupPoint()) {
|
||||
qCritical() << "add or update item to backuplist.xml failed !";
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "CustomizeSystemBackupProxy::doPrepare invoke end";
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 记录/backup/snapshots/backuplist.xml文件
|
||||
* @return true-成功;false-失败
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::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;
|
||||
m_backupPoint.m_os = SystemInfo::m_os;
|
||||
m_backupPoint.m_arch = SystemInfo::m_arch;
|
||||
m_backupPoint.m_archdetect = SystemInfo::m_archDetect;
|
||||
QString xmlPath = m_backupWrapper.m_prefixDestPath + 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 备份系统
|
||||
* @return true,启动备份成功;false,启动备份失败
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::backupSystem()
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::backupSystem invoke begin";
|
||||
|
||||
// 全量备份场景
|
||||
QStringList args = getRsyncArgs(CustomizeSystemBackupScene::SYSTEM_BACKUP);
|
||||
|
||||
// 拼接备份源路径和目标路径
|
||||
QString srcPath = Utils::getSysRootPath();
|
||||
srcPath += "/";
|
||||
srcPath.replace("//", "/");
|
||||
args << srcPath;
|
||||
QString destPath = m_destPath + "/";
|
||||
destPath.replace("//", "/");
|
||||
args << destPath;
|
||||
|
||||
return backup(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 备份系统img文件
|
||||
* @return true,启动备份成功;false,启动备份失败
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::backupImg()
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::backupImg invoke";
|
||||
|
||||
QStringList args;
|
||||
QString srcPath = m_imgPath + "/" + UDISK_MKSQUASHFS_IMG_NAME;
|
||||
QString destPath = m_destPath + "/";
|
||||
destPath.replace("//", "/");
|
||||
args << srcPath << destPath;
|
||||
|
||||
return backup(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 备份公共逻辑
|
||||
* @param args
|
||||
* @return true,启动备份成功;false,启动备份失败
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::backup(const QStringList &args)
|
||||
{
|
||||
qDebug() << "CustomizeSystemBackupProxy::backup invoke begin";
|
||||
|
||||
|
||||
emit checkResult(int(BackupResult::BACKUP_START_SUCCESS));
|
||||
|
||||
do_kylin_security(m_destPath);
|
||||
|
||||
qDebug() << "CustomizeSystemBackupProxy::backup invoke end";
|
||||
return true;
|
||||
}
|
||||
|
||||
void CustomizeSystemBackupProxy::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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 校验移动盘是否还在
|
||||
* @return: bool,存在返回true;不存在返回false
|
||||
* @author: zhaominyong
|
||||
* @since: 2021/05/24
|
||||
* @note:
|
||||
* add by zhaominyong at 2021/05/24 for bug:54377 【备份还原】备份数据到U盘的过程中拔出U盘,备份还原工具仍然一直显示正在备份数据
|
||||
*/
|
||||
bool CustomizeSystemBackupProxy::checkDestDirExists()
|
||||
{
|
||||
if (!m_isFinished)
|
||||
{
|
||||
// 拔掉U盘后,没有响应的场景(怀疑可能是某应用程序关闭引起,希望不是dbus服务关掉了)
|
||||
if (m_isForce) {
|
||||
emit this->workResult(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
|
||||
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
|
||||
m_isForce = true;
|
||||
if (m_calc != nullptr)
|
||||
m_calc->stop();
|
||||
if (m_mksquashfs != nullptr)
|
||||
m_mksquashfs->stop();
|
||||
// 10s钟后如果还没有退出,则强制退出
|
||||
QTimer::singleShot(10*1000, this, &CustomizeSystemBackupProxy::checkDestDirExists);
|
||||
} else {
|
||||
QTimer::singleShot(1*1000, this, &CustomizeSystemBackupProxy::checkDestDirExists);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,4 +1,118 @@
|
|||
#ifndef CUSTOMIZESYSTEMBACKUPPROXY_H
|
||||
#define CUSTOMIZESYSTEMBACKUPPROXY_H
|
||||
|
||||
#include "workerfactory.h"
|
||||
#include "myprocess/calcbackupsize.h"
|
||||
#include "myprocess/mksquashfsprocess.h"
|
||||
#include "parsebackuplist.h"
|
||||
|
||||
class CustomizeSystemBackupProxy : public Worker
|
||||
{
|
||||
Q_OBJECT
|
||||
DECLARE_DYNCREATE(CustomizeSystemBackupProxy)
|
||||
|
||||
public:
|
||||
// 系统备份的几种场景
|
||||
enum CustomizeSystemBackupScene {
|
||||
SYSTEM_BACKUP, // 系统备份
|
||||
TRY_SYSTEM_BACKUP, // 测试系统备份,可用于计算备份传输数据大小
|
||||
MKSQUASHFS, // 生成img文件
|
||||
};
|
||||
|
||||
explicit CustomizeSystemBackupProxy();
|
||||
virtual ~CustomizeSystemBackupProxy();
|
||||
|
||||
public:
|
||||
// 环境检测
|
||||
virtual bool checkEnvEx();
|
||||
|
||||
// 任务处理
|
||||
virtual void doWorkEx();
|
||||
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
// 校验剩余空间是否满足备份
|
||||
void checkFreeCapacity(qint64 itotalSize);
|
||||
|
||||
// mksqushfs
|
||||
void doMksqushfs();
|
||||
|
||||
// 备份
|
||||
void doBackup();
|
||||
|
||||
// 任务取消
|
||||
virtual void cancelEx();
|
||||
|
||||
/**
|
||||
* @brief 校验移动盘是否还在
|
||||
* @return: bool,存在返回true;不存在返回false
|
||||
* @author: zhaominyong
|
||||
* @since: 2021/05/24
|
||||
* @note:
|
||||
* add by zhaominyong at 2021/05/24 for bug:54377 【备份还原】备份数据到U盘的过程中拔出U盘,备份还原工具仍然一直显示正在备份数据
|
||||
*/
|
||||
bool checkDestDirExists();
|
||||
|
||||
private:
|
||||
// 判断是否增量备份
|
||||
bool isIncBackup();
|
||||
|
||||
// 计算备份所需空间大小
|
||||
void calcSizeForBackup();
|
||||
|
||||
/**
|
||||
* @brief 根据场景获取rsync命令参数
|
||||
* @param scene,场景
|
||||
* @return 组装好的rsync的参数信息
|
||||
*/
|
||||
QStringList getRsyncArgs(CustomizeSystemBackupScene scene);
|
||||
|
||||
/**
|
||||
* @brief 记录/backup/snapshots/backuplist.xml文件
|
||||
* @return true-成功;false-失败
|
||||
*/
|
||||
bool recordBackupPoint();
|
||||
|
||||
// 备份准备
|
||||
bool doPrepare();
|
||||
|
||||
// 备份系统
|
||||
bool backupSystem();
|
||||
|
||||
// 备份img文件
|
||||
bool backupImg();
|
||||
|
||||
bool backup(const QStringList &args);
|
||||
|
||||
void do_kylin_security(const QString& dstDir);
|
||||
|
||||
// 失败则删除相应数据
|
||||
void deleteFailedData();
|
||||
|
||||
// 计算备份空间大小的进程
|
||||
CalcBackupSize *m_calc;
|
||||
// 压缩进程
|
||||
MkSquashFSProcess *m_mksquashfs;
|
||||
|
||||
// 是否完成
|
||||
bool m_isFinished;
|
||||
// 是否备份成功
|
||||
bool m_bSuccess;
|
||||
// 当前备份uuid
|
||||
QString m_curUuid;
|
||||
// 当前备份目标目录
|
||||
QString m_destPath;
|
||||
// 当前备份所需空间大小
|
||||
qint64 m_size;
|
||||
// 当前备份节点
|
||||
ParseBackupList::BackupPoint m_backupPoint;
|
||||
// 是否只是检测
|
||||
bool m_isOnlyCheck;
|
||||
// img文件存放路径
|
||||
QString m_imgPath;
|
||||
// 强制结束标志(stop后没反应的情况,系统处于睡眠状态)
|
||||
bool m_isForce;
|
||||
};
|
||||
|
||||
#endif // CUSTOMIZESYSTEMBACKUPPROXY_H
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
QString m_backupName;
|
||||
// 备份时间
|
||||
QString m_time;
|
||||
// 本地备份还是U盘备份: 0-本地备份;1-移动设备备份;2-异机备份(仅用于业务场景标记,不用于持久化记录)
|
||||
// 本地备份还是U盘备份: 0-本地备份;1-移动设备备份;2-异机备份(仅用于业务场景标记,不用于持久化记录);3-自定义路径备份
|
||||
int m_iPosition = -1;
|
||||
// 操作类型,如:系统备份, 系统还原
|
||||
int m_type = -1;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "udisksystembackupproxy.h"
|
||||
|
||||
#include "systembackupproxy.h"
|
||||
#include <QStorageInfo>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
|
|
@ -54,6 +54,8 @@ Worker * WorkerFactory::createWorker(int type, int position)
|
|||
case BackupType::INC_BACKUP_SYSTEM:
|
||||
if (BackupPosition::UDISK == position) {
|
||||
className = "UDiskSystemBackupProxy";
|
||||
} else if (BackupPosition::CUSTOMIZE == position) {
|
||||
className = "CustomizeSystemBackupProxy";
|
||||
} else {
|
||||
className = "SystemBackupProxy";
|
||||
}
|
||||
|
@ -62,6 +64,8 @@ Worker * WorkerFactory::createWorker(int type, int position)
|
|||
case BackupType::RESTORE_SYSTEM_WITH_DATA:
|
||||
if (BackupPosition::UDISK == position) {
|
||||
className = "UDiskSystemRestoreProxy";
|
||||
} else if (BackupPosition::CUSTOMIZE == position) {
|
||||
className = "CustomizeSystemRestoreProxy";
|
||||
} else {
|
||||
className = "SystemRestoreProxy";
|
||||
}
|
||||
|
@ -70,6 +74,8 @@ Worker * WorkerFactory::createWorker(int type, int position)
|
|||
case BackupType::INC_BACKUP_DATA:
|
||||
if (BackupPosition::UDISK == position) {
|
||||
className = "UDiskDataBackupProxy";
|
||||
} else if (BackupPosition::CUSTOMIZE == position) {
|
||||
className = "CustomizeDataBackupProxy";
|
||||
} else {
|
||||
className = "DataBackupProxy";
|
||||
}
|
||||
|
@ -77,6 +83,8 @@ Worker * WorkerFactory::createWorker(int type, int position)
|
|||
case BackupType::RESTORE_DATA:
|
||||
if (BackupPosition::UDISK == position) {
|
||||
className = "UDiskDataRestoreProxy";
|
||||
} else if (BackupPosition::CUSTOMIZE == position) {
|
||||
className = "CustomizeDataRestoreProxy";
|
||||
} else {
|
||||
className = "DataRestoreProxy";
|
||||
}
|
||||
|
@ -87,6 +95,8 @@ Worker * WorkerFactory::createWorker(int type, int position)
|
|||
case BackupType::GHOST_IMAGE:
|
||||
if (BackupPosition::UDISK == position) {
|
||||
className = "UDiskGhostImageProxy";
|
||||
} else if (BackupPosition::CUSTOMIZE == position) {
|
||||
className = "CustomizeGhostImageProxy";
|
||||
} else {
|
||||
className = "GhostImageProxy";
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ enum BackupType {
|
|||
struct BackupWrapper {
|
||||
// 操作类型,如:系统备份, 系统还原
|
||||
int m_type = -1;
|
||||
// 本地备份还是U盘备份: 0-本地备份;1-移动设备备份
|
||||
// 本地备份还是U盘备份: 0-本地备份;1-移动设备备份;2-异机备份;3-自定义路径
|
||||
int m_iPosition = -1;
|
||||
// 备份名称,用于识别备份的,默认是时间
|
||||
QString m_comment;
|
||||
|
@ -163,7 +163,8 @@ enum BackupPosition
|
|||
{
|
||||
LOCAL, // 本地磁盘
|
||||
UDISK, // 移动设备
|
||||
OTHER // 移动设备中的其它机器的备份点
|
||||
OTHER, // 移动设备中的其它机器的备份点
|
||||
CUSTOMIZE, // 自定义路径
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -457,6 +457,7 @@ bool Utils::generateExcludePathsFile()
|
|||
in << "/var/lib/kmre" << END_LINE;
|
||||
in << "/var/lib/udisks2" << END_LINE;
|
||||
in << "/var/log" << END_LINE;
|
||||
in << "*/backup/snapshots" << END_LINE;
|
||||
|
||||
// 系统安装后有的会将/data/home /data/root挂载到的/home /root上,实际文件是存放在/data/home /data/root下面,为了统一标准保留/home /root排除/data/home /data/root
|
||||
QStringList excludes;
|
||||
|
@ -511,6 +512,7 @@ QStringList Utils::getFromExcludePathsFile()
|
|||
list << "/var/lib/kmre";
|
||||
list << "/var/lib/udisks2";
|
||||
list << "/var/log";
|
||||
list << "*/backup/snapshots";
|
||||
|
||||
// 系统安装后有的会将/data/home /data/root挂载到的/home /root上,实际文件是存放在/data/home /data/root下面
|
||||
QStringList excludes;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
#include "filefilterproxymodelforbackup.h"
|
||||
#include <QFileSystemModel>
|
||||
#include "../../common/mydefine.h"
|
||||
|
||||
FileFilterProxyModeForBackup::FileFilterProxyModeForBackup(QObject *parent) :
|
||||
QSortFilterProxyModel(parent)
|
||||
{}
|
||||
|
||||
FileFilterProxyModeForBackup::~FileFilterProxyModeForBackup()
|
||||
{}
|
||||
|
||||
bool FileFilterProxyModeForBackup::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel());
|
||||
|
||||
if (fileModel != nullptr && fileModel->isDir(index0)) {
|
||||
QString fileName = fileModel->fileName(index0);
|
||||
// 防命令注入
|
||||
// 1、形如:mkdir '`id&>id_bak_test.txt`'中的文件夹名称
|
||||
if (fileName.contains(QRegularExpression(".*`.*`.*")))
|
||||
return false;
|
||||
// 2、形如:$()的文件夹名称
|
||||
if (fileName.contains(QRegularExpression(".*\\$\\(.*\\).*")))
|
||||
return false;
|
||||
// 3、形如:${}的文件夹名称
|
||||
if (fileName.contains(QRegularExpression(".*\\$\\{.*\\}.*")))
|
||||
return false;
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
if (fileName.contains(QRegularExpression("[;&|]+")))
|
||||
return false;
|
||||
|
||||
QString filePath = fileModel->filePath(index0);
|
||||
|
||||
return !(filePath.endsWith(BACKUP_SNAPSHOTS_PATH) || filePath == BACKUP_PATH);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,17 @@
|
|||
#ifndef FILEFILTERPROXYMODELFORBACKUP_H
|
||||
#define FILEFILTERPROXYMODELFORBACKUP_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class FileFilterProxyModeForBackup : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileFilterProxyModeForBackup(QObject *parent = nullptr);
|
||||
~FileFilterProxyModeForBackup();
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
|
||||
};
|
||||
|
||||
#endif // FILEFILTERPROXYMODELFORBACKUP_H
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "myfileselect.h"
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLineEdit>
|
||||
#include "filefilterproxymodelforbackup.h"
|
||||
|
||||
MyFileSelect::MyFileSelect(QWidget* parent) :
|
||||
QFileDialog(parent)
|
||||
|
@ -9,6 +10,9 @@ MyFileSelect::MyFileSelect(QWidget* parent) :
|
|||
this->setFileMode(QFileDialog::ExistingFiles);
|
||||
this->setFilter(QDir::System | QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
||||
FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
|
||||
this->setProxyModel(proxy);
|
||||
|
||||
QDialogButtonBox* button = this->findChild<QDialogButtonBox*>("buttonBox");
|
||||
disconnect(button, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(button, SIGNAL(accepted()), this, SLOT(goAccept()));
|
||||
|
|
|
@ -41,6 +41,7 @@ HEADERS += \
|
|||
component/backuplistwidget.h \
|
||||
component/circlelabel.h \
|
||||
component/clicklabel.h \
|
||||
component/filefilterproxymodelforbackup.h \
|
||||
component/hoverwidget.h \
|
||||
component/imageutil.h \
|
||||
component/linelabel.h \
|
||||
|
@ -88,6 +89,7 @@ SOURCES += \
|
|||
component/backuplistwidget.cpp \
|
||||
component/circlelabel.cpp \
|
||||
component/clicklabel.cpp \
|
||||
component/filefilterproxymodelforbackup.cpp \
|
||||
component/hoverwidget.cpp \
|
||||
component/imageutil.cpp \
|
||||
component/linelabel.cpp \
|
||||
|
|
|
@ -288,13 +288,12 @@ void MainDialog::mountBackupPartition()
|
|||
exit(1);
|
||||
} else if (int(MountResult::CANNOT_GET_BACKUPUUID) == reply.value()) {
|
||||
// 没有找到备份分区,只能备份到移动设备中
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
|
||||
QObject::tr("Please check if the backup partition exists which can be created when you install the Operating System."),
|
||||
QObject::tr("Ok"));
|
||||
|
||||
// GlobelBackupInfo::inst().setHasBackupPartition(false);
|
||||
// 此时还未进入应用的事件循环中,故不能使用qApp->quit();
|
||||
exit(1);
|
||||
// MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
|
||||
// QObject::tr("Please check if the backup partition exists which can be created when you install the Operating System."),
|
||||
// QObject::tr("Ok"));
|
||||
// // 此时还未进入应用的事件循环中,故不能使用qApp->quit();
|
||||
// exit(1);
|
||||
GlobelBackupInfo::inst().setHasBackupPartition(false);
|
||||
} else if (int(MountResult::MOUNTED) != reply.value()) {
|
||||
// 挂载备份分区失败
|
||||
MessageBoxUtils::QMESSAGE_BOX_CRITICAL(this, QObject::tr("Warning"),
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
#include <QMovie>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFileDialog>
|
||||
#include <QtGlobal>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../component/clicklabel.h"
|
||||
#include "../component/circlelabel.h"
|
||||
#include "../component/filefilterproxymodelforbackup.h"
|
||||
#include "../component/myiconlabel.h"
|
||||
#include "../component/mylabel.h"
|
||||
#include "../component/mylineedit.h"
|
||||
|
@ -246,8 +249,49 @@ void SystemBackup::initSecondWidget()
|
|||
comboSelect->addItem(iconFolder, qsPreDevPath + disk.rootPath() + BACKUP_SNAPSHOTS_PATH);
|
||||
}
|
||||
});
|
||||
connect(comboSelect, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=]() {
|
||||
this->m_prefixDestPath = "";
|
||||
});
|
||||
m_udector->getStorageInfo();
|
||||
QPushButton *buttonBrowse = new QPushButton;
|
||||
buttonBrowse->setText(tr("Browse..."));
|
||||
connect(buttonBrowse, &QPushButton::clicked, this, [=](){
|
||||
// 是否自定义路径?自定义路径备份文件不受保护,可能导致备份文件丢失或损坏
|
||||
if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(this, QObject::tr("Information"),
|
||||
QObject::tr("Are you sure to continue customizing the path?\n"
|
||||
"The custom path backup file is not protected, which may cause the backup file to be lost or damaged"),
|
||||
QObject::tr("Ok"), QObject::tr("Cancel")))
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
QFileDialog fileDialog(this);
|
||||
fileDialog.setWindowTitle(tr("Please select a path"));
|
||||
fileDialog.setViewMode(QFileDialog::List);
|
||||
fileDialog.setFileMode(QFileDialog::DirectoryOnly);
|
||||
fileDialog.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
QList<QUrl> siderUrls;
|
||||
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath());
|
||||
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath() + "/data");
|
||||
fileDialog.setSidebarUrls(siderUrls);
|
||||
FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
|
||||
fileDialog.setProxyModel(proxy);
|
||||
if (fileDialog.exec() == QDialog::Accepted) {
|
||||
QStringList selectFiles = fileDialog.selectedFiles();
|
||||
if (!selectFiles.isEmpty()) {
|
||||
comboSelect->setCurrentIndex(-1);
|
||||
QString fileName = selectFiles.at(0);
|
||||
this->m_prefixDestPath = fileName;
|
||||
|
||||
QLineEdit * edit = new QLineEdit;
|
||||
comboSelect->setLineEdit(edit);
|
||||
edit->setText(tr("customize path : ") + fileName + BACKUP_SNAPSHOTS_PATH);
|
||||
edit->setReadOnly(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
hlayoutLine2->addWidget(comboSelect);
|
||||
hlayoutLine2->addWidget(buttonBrowse);
|
||||
hlayoutLine2->addSpacing(40);
|
||||
vlayout->addLayout(hlayoutLine2);
|
||||
vlayout->addSpacing(30);
|
||||
|
@ -272,9 +316,14 @@ void SystemBackup::initSecondWidget()
|
|||
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
|
||||
// 备份路径选择索引
|
||||
int index = comboSelect->currentIndex();
|
||||
// 第一个选项是本地系统备份
|
||||
this->m_isLocal = GlobelBackupInfo::inst().hasBackupPartition() && (index == 0);
|
||||
this->m_prefixDestPath = this->m_udiskPaths.at(index);
|
||||
if (index >= 0) {
|
||||
// 第一个选项是本地系统备份
|
||||
this->m_isLocal = GlobelBackupInfo::inst().hasBackupPartition() && (index == 0);
|
||||
this->m_prefixDestPath = this->m_udiskPaths.at(index);
|
||||
} else {
|
||||
// 自定义备份位置的场景
|
||||
this->m_isLocal = true;
|
||||
}
|
||||
this->on_next_clicked(checked);
|
||||
emit this->startCheckEnv();
|
||||
});
|
||||
|
@ -561,7 +610,7 @@ void SystemBackup::on_checkEnv_start()
|
|||
BackupWrapper backupWrapper;
|
||||
backupWrapper.m_backupName = m_backupName;
|
||||
backupWrapper.m_type = BackupType::BACKUP_SYSTEM;
|
||||
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
|
||||
backupWrapper.m_iPosition = m_isLocal ? (this->m_prefixDestPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::CUSTOMIZE) : BackupPosition::UDISK;
|
||||
QString backupPath = Utils::getSysRootPath();
|
||||
backupPath += "/";
|
||||
backupPath.replace("//", "/");
|
||||
|
@ -1062,7 +1111,7 @@ void SystemBackup::on_backup_start()
|
|||
BackupWrapper backupWrapper;
|
||||
backupWrapper.m_backupName = m_backupName;
|
||||
backupWrapper.m_type = BackupType::BACKUP_SYSTEM;
|
||||
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
|
||||
backupWrapper.m_iPosition = m_isLocal ? (this->m_prefixDestPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::CUSTOMIZE) : BackupPosition::UDISK;
|
||||
QString backupPath = Utils::getSysRootPath();
|
||||
backupPath += "/";
|
||||
backupPath.replace("//", "/");
|
||||
|
|
Loading…
Reference in New Issue