fixed #I7DFN9 #I7DF5I #I72LFX #I72P8K #I5XHG7
This commit is contained in:
parent
779441b092
commit
120794a195
|
@ -1,5 +1,11 @@
|
|||
[Desktop Entry]
|
||||
Name=backup-daemon
|
||||
Name[zh_CN]=备份还原守护进程
|
||||
Name[zh_HK]=備份還原守護進程
|
||||
Name[bo_CN]=གྲབས་ཉར་སོར་ལོག་ལྟ་སྲུང་འཕེལ་རིམ་
|
||||
Name[mn]=ᠨᠥᠭᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠵᠤ ᠰᠠᠬᠢᠬᠤ ᠠᠬᠢᠴᠠ
|
||||
Type=Application
|
||||
Comment=The daemon process of kybackup.
|
||||
Exec=/usr/bin/backup-daemon %U
|
||||
Icon=yhkylin-backup-tools
|
||||
NoDisplay=true
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <QStorageInfo>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
#include "../common/utils.h"
|
||||
#include "../common/mydusizetool.h"
|
||||
#include "mymountproxy.h"
|
||||
|
@ -54,6 +55,21 @@ bool CustomizeDataBackupProxy::checkEnvEx()
|
|||
return false;
|
||||
}
|
||||
|
||||
// 防命令注入
|
||||
// 1、形如:mkdir '`id&>id_bak_test.txt`'中的文件夹名称
|
||||
// 2、形如:$()的文件夹名称
|
||||
// 3、形如:${}的文件夹名称
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
|
||||
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
|
||||
|
||||
emit checkResult(int(BackupResult::DU_ERR));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
|
||||
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
|
||||
Utils::mkpath(m_backupWrapper.m_prefixDestPath);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QRegularExpression>
|
||||
#include "../common/utils.h"
|
||||
#include "../common/mydusizetool.h"
|
||||
#include "mymountproxy.h"
|
||||
|
@ -60,6 +61,21 @@ bool CustomizeSystemBackupProxy::checkEnvEx()
|
|||
return false;
|
||||
}
|
||||
|
||||
// 防命令注入
|
||||
// 1、形如:mkdir '`id&>id_bak_test.txt`'中的文件夹名称
|
||||
// 2、形如:$()的文件夹名称
|
||||
// 3、形如:${}的文件夹名称
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
|
||||
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
|
||||
|
||||
emit checkResult(int(BackupResult::DU_ERR));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Utils::isDirEmpty(m_backupWrapper.m_prefixDestPath)) {
|
||||
qCritical() << QString("dstDir %s is not exist!").arg(m_backupWrapper.m_prefixDestPath);
|
||||
Utils::mkpath(m_backupWrapper.m_prefixDestPath);
|
||||
|
@ -230,6 +246,7 @@ QStringList CustomizeSystemBackupProxy::getRsyncArgs(CustomizeSystemBackupScene
|
|||
args << "--ignore-missing-args";
|
||||
break ;
|
||||
case CustomizeSystemBackupScene::MKSQUASHFS :
|
||||
// (在mksquashfs时排除bind挂载的任意一方时,都备份不上)
|
||||
Utils::excludeFstabBindPath(excludes);
|
||||
// --exclude=排除路径设置
|
||||
for (QString item : m_backupWrapper.m_backupExcludePaths) {
|
||||
|
|
|
@ -115,18 +115,20 @@ bool CustomizeSystemRestoreProxy::doPrepare()
|
|||
if (!mountImg())
|
||||
return false;
|
||||
|
||||
// 2、停止安全防护
|
||||
QProcess::execute("systemctl stop kysec-init.service");
|
||||
// 2、停止安全初始化服务,以防过高的CPU占有率,因为还原时安全初始化服务会逐个文件打标记,造成cpu占有率超高系统卡顿
|
||||
Utils::stopKysecInit();
|
||||
// 停止网络服务,以防网络更新
|
||||
Utils::stopNetwork();
|
||||
|
||||
// 3、以读写方式重新挂载boot分区,因为有的机器默认以只读挂载
|
||||
remountBoot();
|
||||
Utils::remountBoot();
|
||||
|
||||
// 4、是否有/boot/efi目录,有则认为有efi分区,需重新rw挂载
|
||||
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
efiPath.replace("//", "/");
|
||||
if (!Utils::isDirEmpty(efiPath)) {
|
||||
// 重新rw读写挂载
|
||||
remountEfi();
|
||||
Utils::remountEfi();
|
||||
}
|
||||
|
||||
qDebug() << "CustomizeSystemRestoreProxy::doPrepare invoke end";
|
||||
|
|
|
@ -29,16 +29,11 @@ rootpath=$2
|
|||
m_mountPath=$3
|
||||
m_default_uuid=$4
|
||||
|
||||
BACKUP=
|
||||
if [[ -e "${rootpath}/backup/BACKUP/snapshots" ]]; then
|
||||
BACKUP="/BACKUP"
|
||||
fi
|
||||
|
||||
m_backuplistPath=${m_mountPath}${BACKUP}"/snapshots/backuplist.xml"
|
||||
EXCLUDEFILE=${m_mountPath}${BACKUP}"/snapshots/.exclude"
|
||||
PLOGFILEDIR="${m_mountPath}${BACKUP}/log"
|
||||
m_backuplistPath="${m_mountPath}/snapshots/backuplist.xml"
|
||||
EXCLUDEFILE="${m_mountPath}/snapshots/.exclude"
|
||||
PLOGFILEDIR="${m_mountPath}/log"
|
||||
PLOGFILE="$PLOGFILEDIR/log-$(date +%Y%m%d%H%M)"
|
||||
LOGFILE="${m_mountPath}${BACKUP}/log.txt" #LOGFILE="/tmp/log.txt"
|
||||
LOGFILE="${m_mountPath}/log.txt" #LOGFILE="/tmp/log.txt"
|
||||
|
||||
#是否是出厂备份
|
||||
m_isFactory=false
|
||||
|
@ -49,7 +44,7 @@ PERSONAL_BACKUPFILE=".user.txt"
|
|||
m_isRetainUserData=false
|
||||
|
||||
#如果/backup不存在,则创建该目录
|
||||
mkdir -p ${m_mountPath}${BACKUP}
|
||||
mkdir -p ${m_mountPath}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Could not create /backup in initrd!"
|
||||
exit 20
|
||||
|
@ -111,7 +106,7 @@ getBackupInfo() {
|
|||
|
||||
#该函数是对backup-daemon/parsebackuplist.cpp中相应函数的替换
|
||||
createBackupList() {
|
||||
local backuplistDir=${m_mountPath}${BACKUP}"/snapshots/"
|
||||
local backuplistDir="${m_mountPath}/snapshots/"
|
||||
|
||||
if [ ! -e "$backuplistDir" ]; then
|
||||
mkdir -p $backuplistDir
|
||||
|
@ -653,8 +648,8 @@ backuping() {
|
|||
|
||||
#0:backup 1:restore
|
||||
generateExcludeFile 0
|
||||
echo "/" > ${m_mountPath}${BACKUP}/snapshots/$m_uuid/$PERSONAL_BACKUPFILE
|
||||
cp $EXCLUDEFILE ${m_mountPath}${BACKUP}/snapshots/$m_uuid/$PERSONAL_EXCLUDEFILE
|
||||
echo "/" > ${m_mountPath}/snapshots/$m_uuid/$PERSONAL_BACKUPFILE
|
||||
cp $EXCLUDEFILE ${m_mountPath}/snapshots/$m_uuid/$PERSONAL_EXCLUDEFILE
|
||||
|
||||
#echo "Begin to backup efi directory..." >>$PLOGFILE
|
||||
#echo "Begin to backup efi directory..."
|
||||
|
@ -826,8 +821,8 @@ deleteItemByComment() {
|
|||
}
|
||||
|
||||
DeleteFactoryBackup() {
|
||||
if [ -e "/backup${BACKUP}/snapshots/{${factory_uuid}}" ]; then
|
||||
rm /backup${BACKUP}/snapshots/{${factory_uuid}} -rf
|
||||
if [ -e "/backup/snapshots/{${factory_uuid}}" ]; then
|
||||
rm /backup/snapshots/{${factory_uuid}} -rf
|
||||
fi
|
||||
|
||||
local comment=$(findCommentByUuid "{${factory_uuid}}")
|
||||
|
@ -862,7 +857,7 @@ backupAuto() { #备份
|
|||
# echo "BYbobbi: m_uuid is $m_uuid"
|
||||
m_time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
|
||||
m_comment=$m_time #这个是全局变量
|
||||
dst="${m_mountPath}${BACKUP}/snapshots/$m_uuid/data"
|
||||
dst="${m_mountPath}/snapshots/$m_uuid/data"
|
||||
#echo "dst: $dst"
|
||||
mkdir -p $dst
|
||||
m_size=$global_system_usedDisk
|
||||
|
@ -942,7 +937,7 @@ backupAuto() { #备份
|
|||
rm -f $tmpFile
|
||||
|
||||
#写文件
|
||||
metainfo_file="${m_mountPath}${BACKUP}/snapshots/$m_uuid/$METAINFO"
|
||||
metainfo_file="${m_mountPath}/snapshots/$m_uuid/$METAINFO"
|
||||
#echo "metainfo_file="$metainfo_file
|
||||
#第1行清空写
|
||||
#这里写的不是xml文件,是一个文本文件,这时候的状态是backup unfinished
|
||||
|
@ -958,12 +953,13 @@ backupAuto() { #备份
|
|||
|
||||
#返回值:
|
||||
getLastUsefulBackupPointUuid() {
|
||||
local xxx currentUuid foundComment
|
||||
local xxx currentUuid foundComment currentComment
|
||||
currentUuid=""
|
||||
currentState=false
|
||||
currentType=true
|
||||
lastUsefulBackupPointUuid=""
|
||||
foundComment=0 #是否发现了要修改的comment
|
||||
currentComment=""
|
||||
lastbackupname=""
|
||||
|
||||
#如果不定义IFS,则echo $line会去掉前后空格,导致写到文件中去时没有格式
|
||||
|
@ -975,7 +971,7 @@ getLastUsefulBackupPointUuid() {
|
|||
#echo "xxx: $xxx"
|
||||
|
||||
if [[ "$xxx" =~ "<Comment>" ]]; then
|
||||
lastbackupname=$xxx
|
||||
currentComment=$xxx
|
||||
fi
|
||||
|
||||
if [[ "$xxx" =~ "<Uuid>" ]]; then
|
||||
|
@ -1004,6 +1000,7 @@ getLastUsefulBackupPointUuid() {
|
|||
if [[ "$xxx" =~ "</BackupPoint>" ]]; then
|
||||
if [ "$currentState" = true -a "$currentType" = true ]; then #"/backup"是不是一个独立的盘
|
||||
lastUsefulBackupPointUuid=$currentUuid
|
||||
lastbackupname=$currentComment
|
||||
fi
|
||||
fi
|
||||
done <"$m_backuplistPath"
|
||||
|
@ -1041,7 +1038,7 @@ restoreAuto() { #还原
|
|||
local m_time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
|
||||
writeLogFile "${m_time},${uuid},4,grub系统还原,,,${lastbackupname}" #grub时只有一键还原,没有增量还原
|
||||
|
||||
restoreDir="${m_mountPath}${BACKUP}/snapshots/$uuid"
|
||||
restoreDir="${m_mountPath}/snapshots/$uuid"
|
||||
|
||||
if [ ! -e "$restoreDir" ]; then
|
||||
echo "full restore directory not exists!"
|
||||
|
@ -1165,18 +1162,29 @@ restoreAuto() { #还原
|
|||
echo "restore other directories end"
|
||||
echo "restore other directories end" >>$PLOGFILE
|
||||
sync
|
||||
#还原时清空目录
|
||||
#if [ -e "$rootpath/home/data" ]; then
|
||||
# rm -r "$rootpath/home/data" ]
|
||||
#fi
|
||||
#mkdir -p "$rootpath/home/data" ]
|
||||
grub-install
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
#see backup-auto/autobackup.cpp
|
||||
updateBackupAutoFinishedState() {
|
||||
echo "this is updateBackupAutoFinishedState"
|
||||
}
|
||||
|
||||
restoreBackupSelf() {
|
||||
restoreDir="${rootpath}/var/log/yhkylin-backup-tools"
|
||||
echo $restoreDir
|
||||
|
||||
if [ ! -e "$restoreDir" ]; then
|
||||
echo "restoreBackupSelf error: no files"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 还原rsync/kybackup/backup-daemon等程序
|
||||
rsync -avAXHr ${restoreDir}/backup-daemon ${rootpath}/usr/bin/ >> ${rootpath}/var/log/backup.log 2>&1
|
||||
rsync -avAXHr ${restoreDir}/kybackup ${rootpath}/usr/bin/ >> ${rootpath}/var/log/backup.log 2>&1
|
||||
|
||||
rm -rf ${restoreDir}
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
|
@ -1187,13 +1195,16 @@ if [ "${rootpath}" = "/" ]; then
|
|||
# exit
|
||||
fi
|
||||
|
||||
getBackupInfo
|
||||
#echo "m_restoreUuid="$m_restoreUuid
|
||||
#echo "m_enabled="$m_enabled
|
||||
#不加引号报错
|
||||
if [ "$m_restoreUuid" = "" ] || [ "$m_enabled" = "" ]; then
|
||||
echo "bootinfo file is not correct!"
|
||||
exit 3
|
||||
# 还原自身不需要挂载备份分区
|
||||
if [ $backupORrestore != "--restorebackupself" ]; then
|
||||
getBackupInfo
|
||||
#echo "m_restoreUuid="$m_restoreUuid
|
||||
#echo "m_enabled="$m_enabled
|
||||
#不加引号报错
|
||||
if [ "$m_restoreUuid" = "" ] || [ "$m_enabled" = "" ]; then
|
||||
echo "bootinfo file is not correct!"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p ${rootpath}/var/log
|
||||
|
@ -1241,6 +1252,8 @@ elif [ $backupORrestore = "--factoryrestore" ]; then
|
|||
#umountBackup
|
||||
|
||||
echo "This is factorybackup"
|
||||
elif [ $backupORrestore = "--restorebackupself" ]; then
|
||||
restoreBackupSelf
|
||||
else
|
||||
echo "Not correct command"
|
||||
exit 18
|
||||
|
|
|
@ -65,6 +65,7 @@ ExistCopyExec /bin/ls /bin
|
|||
ExistCopyExec /bin/mount /bin
|
||||
ExistCopyExec /bin/sync /bin
|
||||
ExistCopyExec /sbin/reboot /bin
|
||||
ExistCopyExec /sbin/grub-install /bin
|
||||
#fix wrong timezone in initrd(#)
|
||||
#ExistCopyExec /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ echo $*
|
|||
BACKUP_FLAG=backup
|
||||
RESTORE_FLAG=restore
|
||||
ROLLBACK_FLAG=rollback-backup
|
||||
IS_NORMAL=
|
||||
|
||||
#. /scripts/security-functions
|
||||
show_text_mesg()
|
||||
|
@ -133,7 +134,7 @@ is_990_9a0=$(get_is_990_9a0)
|
|||
|
||||
factory_restore_warnning()
|
||||
{
|
||||
if [ x${is_990_9a0} == x"true" ]; then
|
||||
if [[ x${is_990_9a0} == x"true" && x${FACTORY_RESTORE} == "xy" ]]; then
|
||||
local is_sure=
|
||||
while :
|
||||
do
|
||||
|
@ -156,7 +157,7 @@ factory_restore_warnning()
|
|||
|
||||
factory_restore_warnning_again()
|
||||
{
|
||||
if [ x${is_990_9a0} == x"true" ]; then
|
||||
if [[ x${is_990_9a0} == x"true" && x"$FACTORY_RESTORE" = "xy" ]]; then
|
||||
local is_sure=
|
||||
while :
|
||||
do
|
||||
|
@ -310,6 +311,7 @@ for x in $(cat /proc/cmdline); do
|
|||
FACTORY_RESTORE=y
|
||||
;;
|
||||
*)
|
||||
IS_NORMAL=y
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
|
|
@ -52,6 +52,7 @@ bool MountBackupProcess::umountBackupPartition()
|
|||
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
|
||||
backupPath.replace("//","/");
|
||||
QStringList arguments;
|
||||
arguments << "-R";
|
||||
arguments << backupPath;
|
||||
m_p->start("umount", arguments);
|
||||
if (!m_p->waitForStarted()) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<Type>2</Type>
|
||||
<Position>0</Position>
|
||||
<UserId>1000</UserId>
|
||||
<PrefixDestPath>/</PrefixDestPath>
|
||||
</BackupPoint>
|
||||
</backupList>
|
||||
*/
|
||||
|
@ -299,7 +300,10 @@ void ParseBackupList::getCustomizePaths(QStringList &customizePaths)
|
|||
|
||||
QDomElement elePrefixPath = node.firstChildElement(PREFIXDESTPATH);
|
||||
if (!elePrefixPath.isNull()) {
|
||||
customizePaths << elePrefixPath.text() + BACKUP_SNAPSHOTS_PATH;
|
||||
QString prefixPath = elePrefixPath.text() + BACKUP_SNAPSHOTS_PATH;
|
||||
prefixPath.replace("//", "/");
|
||||
if (!customizePaths.contains(prefixPath))
|
||||
customizePaths << prefixPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -512,10 +516,10 @@ ParseBackupList::ParseResult ParseBackupList::updateItem(const BackupPoint & bac
|
|||
if (i < list.count()) {
|
||||
// 移除旧节点,更新后的节点放到最后
|
||||
root.removeChild(list.at(i));
|
||||
QDomElement newNode = doc.createElement(BACKUPPOINT);
|
||||
backupPointToElementNode(backupPoint, doc, newNode);
|
||||
root.appendChild(newNode);
|
||||
}
|
||||
QDomElement newNode = doc.createElement(BACKUPPOINT);
|
||||
backupPointToElementNode(backupPoint, doc, newNode);
|
||||
root.appendChild(newNode);
|
||||
|
||||
QFile xmlFile(m_xmlPath);
|
||||
if (!xmlFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
|
|
|
@ -120,30 +120,36 @@ void SystemBackupProxy::deleteFailedData()
|
|||
bool SystemBackupProxy::isIncBackup()
|
||||
{
|
||||
QString backupPath;
|
||||
ParseBackupList::BackupPoint point;
|
||||
if (m_backupWrapper.m_uuid.isEmpty()) {
|
||||
QString xmlPath(Utils::getSysRootPath() + BACKUP_XML_PATH);
|
||||
xmlPath.replace("//", "/");
|
||||
ParseBackupList parser(xmlPath);
|
||||
ParseBackupList::BackupPoint point;
|
||||
point = parser.getLastSysBackupPoint();
|
||||
if (point.m_uuid.isEmpty())
|
||||
return false;
|
||||
backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + point.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;
|
||||
}
|
||||
} else {
|
||||
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
|
||||
xmlPath.replace("//", "/");
|
||||
ParseBackupList parse(xmlPath);
|
||||
m_backupPoint = parse.findBackupPointByUuid(m_backupWrapper.m_uuid);
|
||||
backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
|
||||
backupPath.replace("//", "/");
|
||||
if (!m_backupPoint.m_backupName.isEmpty()) {
|
||||
m_backupWrapper.m_bIncrement = true;
|
||||
m_backupWrapper.m_type = BackupType::INC_BACKUP_SYSTEM;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
backupPath.replace("//", "/");
|
||||
if (Utils::isDirExist(backupPath) && !point.m_backupName.isEmpty()) {
|
||||
m_backupWrapper.m_baseUuid = point.m_uuid;
|
||||
m_backupWrapper.m_bIncrement = true;
|
||||
m_backupWrapper.m_type = BackupType::INC_BACKUP_SYSTEM;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -399,10 +405,11 @@ bool SystemBackupProxy::recordBackupPoint()
|
|||
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_path = m_backupWrapper.m_prefixDestPath;
|
||||
QString xmlPath = Utils::getSysRootPath() + BACKUP_XML_PATH;
|
||||
xmlPath.replace("//", "/");
|
||||
ParseBackupList parse(xmlPath);
|
||||
if (m_backupWrapper.m_uuid.isEmpty() || !m_backupWrapper.m_bIncrement) {
|
||||
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;
|
||||
|
|
|
@ -113,6 +113,9 @@ bool SystemRestoreProxy::restoreEfi()
|
|||
{
|
||||
qDebug() << "SystemRestoreProxy::restoreEfi invoke begin";
|
||||
|
||||
// 以读写方式重新挂载boot分区,因为有的机器默认以只读挂载
|
||||
Utils::remountBoot();
|
||||
|
||||
// 是否有/boot/efi目录
|
||||
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
efiPath.replace("//", "/");
|
||||
|
@ -122,7 +125,7 @@ bool SystemRestoreProxy::restoreEfi()
|
|||
sync();
|
||||
|
||||
// 2、重新rw读写挂载
|
||||
remountEfi();
|
||||
Utils::remountEfi();
|
||||
|
||||
// 3、同步efi
|
||||
return rsyncEfi();
|
||||
|
@ -149,34 +152,6 @@ void SystemRestoreProxy::repairEfi()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载efi分区
|
||||
*/
|
||||
void SystemRestoreProxy::remountEfi()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载boot分区
|
||||
*/
|
||||
void SystemRestoreProxy::remountBoot()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 同步efi
|
||||
*/
|
||||
|
@ -286,7 +261,7 @@ QStringList SystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
|
|||
args << "--exclude=/usr/bin/rsync";
|
||||
args << "--exclude=/usr/share/rsync";
|
||||
args << "--exclude=/usr/share/initramfs-tools/hooks/kybackup-hooks";
|
||||
args << "--exclude=/usr/share/initramfs-tools/scripts/local-bottom/kybackup";
|
||||
args << "--exclude=/usr/share/initramfs-tools/scripts/*/kybackup";
|
||||
|
||||
// 还原后仍然保持激活状态
|
||||
args << "--exclude=/etc/LICENSE";
|
||||
|
@ -363,16 +338,15 @@ QStringList SystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
|
|||
*/
|
||||
void SystemRestoreProxy::restoreSystem()
|
||||
{
|
||||
// 停止安全防护
|
||||
QProcess::execute("systemctl stop kysec-init.service");
|
||||
// 停止安全初始化服务,以防过高的CPU占有率,因为还原时安全初始化服务会逐个文件打标记,造成cpu占有率超高系统卡顿
|
||||
Utils::stopKysecInit();
|
||||
// 停止网络服务,以防网络更新
|
||||
Utils::stopNetwork();
|
||||
|
||||
// 本地系统备份没有img挂载,故下面两个路径相等
|
||||
m_srcPath = m_backupPath;
|
||||
QString destPath = Utils::getSysRootPath();
|
||||
|
||||
// 以读写方式重新挂载boot分区,因为有的机器默认以只读挂载
|
||||
remountBoot();
|
||||
|
||||
QStringList args;
|
||||
// 自动更新的备份还原时保留用户数据
|
||||
if (m_curUuid == AUTO_BACKUP_UUID || m_backupWrapper.m_type == BackupType::RESTORE_SYSTEM_WITH_DATA) {
|
||||
|
@ -395,6 +369,15 @@ void SystemRestoreProxy::restoreSystem()
|
|||
// Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,," + QString::number(m_backupWrapper.m_frontUid));
|
||||
Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,,," + m_backupPoint.m_backupName);
|
||||
|
||||
// 华为9a0等机型设定1分钟后关机重启,原因:运行时还原备份还原工具本身可能会造成运行中的备份还原崩溃,从而无法执行到后面的自动重启代码,故在此预设。
|
||||
// 不再只华为机型使用此方法,将全部机型都改为此方法,缩短操作链
|
||||
// if (Utils::isHuawei990())
|
||||
{
|
||||
QString msg;
|
||||
Utils::executeCMD("shutdown -r +1", msg);
|
||||
qDebug() << msg;
|
||||
}
|
||||
|
||||
Utils::updateSyncFile();
|
||||
Utils::wait(2);
|
||||
QString fileIfSync = Utils::getSysRootPath() + FILE_IF_SYNC;
|
||||
|
@ -417,7 +400,9 @@ void SystemRestoreProxy::restoreSystem()
|
|||
removeHome(QString(Utils::getSysRootPath() + "/data/home").replace("//", "/"));
|
||||
}
|
||||
|
||||
QProcess::execute("sync");
|
||||
// 最后,再一次还原home目录以查缺补漏,因为系统还原过程中~/.config等目录中的部分文件可能会更新,会引起部分bug(如任务栏固定图标还原不完整等)
|
||||
this->rsyncAgain();
|
||||
::sync();
|
||||
// 2209后新增了一些依赖,还原到以前的4.0.13版后缺少依赖无法运行,故此最后还得还原backup-daemon和kybackup本身
|
||||
// 兼容Qt库从5.12.8升级到5.15,系统还原的最后也将备份还原工具本身还原
|
||||
// QString version = Utils::getBackupVersion();
|
||||
|
@ -425,22 +410,32 @@ void SystemRestoreProxy::restoreSystem()
|
|||
if (Utils::getSysRootPath() != CASPER_ROOT_PATH)
|
||||
{
|
||||
// initrd.img已经还原为旧状态,需要将新版本的backup-auto-efi等脚本文件更新到initrd.img中,这样我们修改后的新逻辑才能生效
|
||||
// QString msg;
|
||||
// Utils::executeCMD("update-initramfs -u", msg);
|
||||
// qDebug() << msg;
|
||||
|
||||
// 解决bug:182576 【2203自适应升级2309】【2303自适应升级2309】升级成功还原系统失败,应该是有更新包修改了UEFI固件查找引导器文件的引导地址
|
||||
// 故系统还原完成后,重新执行下grub-install命令
|
||||
QString msg;
|
||||
Utils::executeCMD("update-initramfs -u", msg);
|
||||
Utils::executeCMD("grub-install", msg);
|
||||
qDebug() << msg;
|
||||
|
||||
// 写入标记:rsync_backup_self:${UUID}到文件/etc/file_if_sync中,表示需要还原backup-daemon和kybackup本身
|
||||
QString line("rsync_backup_self:");
|
||||
line += m_curUuid;
|
||||
Utils::syncWriteFile(fileIfSync, line);
|
||||
// QString line("rsync_backup_self:");
|
||||
// line += m_curUuid;
|
||||
// Utils::syncWriteFile(fileIfSync, line);
|
||||
// this->undoRestoreData();
|
||||
|
||||
// 加一层保险(因为有些机型上使用"update-initramfs -u"命令会失败,如:华为9006c的2203版等)
|
||||
// QString version = Utils::getBackupVersion();
|
||||
// if (Utils::isHuawei990() && version.contains("4.0.13"))
|
||||
this->rsyncBackupSelf();
|
||||
|
||||
::sync();
|
||||
// Utils::wait(5);
|
||||
}
|
||||
|
||||
Utils::wait(5);
|
||||
emit this->workResult(result);
|
||||
Utils::wait(2);
|
||||
|
||||
Utils::wait(3);
|
||||
reboot(RB_AUTOBOOT);
|
||||
} else {
|
||||
emit this->workResult(result);
|
||||
|
@ -545,3 +540,78 @@ void SystemRestoreProxy::removeHome(const QString& path)
|
|||
|
||||
qDebug() << "SystemRestoreProxy::removeHome invoke end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 再一次同步
|
||||
* @note 意图通过多次同步查缺补漏,如:
|
||||
* 1、因为系统还原过程中~/.config等目录中的部分文件可能会更新,会引起部分bug:
|
||||
* a. 配网,打开奇安信浏览器,触发自动更新(或者软件商店手动更新),且奇安信默认固定在任务栏;
|
||||
* b. 下载安装微信,固定任务栏(新装任意第三方软件均可),会删除desktop文件
|
||||
* c. 上面两种操作,都会触发任务栏配置更新;通过监控任务栏配置文件,在系统还原过程中,可以明显的看到,在还原1%的时候,配置文件还原到历史文件,桌面图标还原,然后下一秒配置文件就又更新成当前最新的了
|
||||
*/
|
||||
void SystemRestoreProxy::rsyncAgain()
|
||||
{
|
||||
// 保留用户数据还原直接
|
||||
if (m_bRetainUserData)
|
||||
return ;
|
||||
|
||||
QString destPath = Utils::getSysRootPath() + "/home/";
|
||||
destPath.replace("//", "/");
|
||||
Utils::mkpath(destPath);
|
||||
|
||||
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
|
||||
QStringList args;
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/home/";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 未做完的还原,需要在重启后initrd阶段执行备份还原脚本时再进行还原
|
||||
* @note 当前只有备份工具自身未还原
|
||||
*/
|
||||
void SystemRestoreProxy::undoRestoreData()
|
||||
{
|
||||
QString destPath = Utils::getSysRootPath() + "/var/log/yhkylin-backup-tools/";
|
||||
destPath.replace("//", "/");
|
||||
Utils::mkpath(destPath);
|
||||
|
||||
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
|
||||
QStringList args;
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/backup-daemon";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
|
||||
args.clear();
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/kybackup";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 还原备份还原工具自身
|
||||
* @note 在undoRestoreData基础上增加的一层保险(因为有些机型上使用"update-initramfs -u"命令会失败,如:华为9006c的2203版等)
|
||||
* 本来想在/etc/profile.d/目录或/etc/init.d/目录等下面增加一个.sh脚本文件以开机时自动执行,但试验了几种方式均都未执行,原因未知。
|
||||
*/
|
||||
void SystemRestoreProxy::rsyncBackupSelf()
|
||||
{
|
||||
QString destPath = Utils::getSysRootPath() + "/usr/bin/";
|
||||
destPath.replace("//", "/");
|
||||
Utils::mkpath(destPath);
|
||||
|
||||
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
|
||||
QStringList args;
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/kybackup";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
|
||||
args.clear();
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/backup-daemon";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
}
|
||||
|
|
|
@ -32,10 +32,6 @@ private:
|
|||
bool restoreEfi();
|
||||
// 修复efi目录
|
||||
void repairEfi();
|
||||
// 以读写方式重新挂载efi分区
|
||||
void remountEfi();
|
||||
// 以读写方式重新挂载boot分区
|
||||
void remountBoot();
|
||||
// 同步efi
|
||||
bool rsyncEfi();
|
||||
// 系统还原
|
||||
|
@ -45,6 +41,20 @@ private:
|
|||
// 获取备份点里存在家目录的用户列表
|
||||
QStringList getBackupPointUsers();
|
||||
QStringList getBackupPointUsers(const QString& path);
|
||||
// 待还原数据
|
||||
void undoRestoreData();
|
||||
// 还原备份还原工具自身
|
||||
void rsyncBackupSelf();
|
||||
|
||||
/**
|
||||
* @brief 再一次同步
|
||||
* @note 意图通过多次同步查缺补漏,如:
|
||||
* 1、因为系统还原过程中~/.config等目录中的部分文件可能会更新,会引起部分bug:
|
||||
* a. 配网,打开奇安信浏览器,触发自动更新(或者软件商店手动更新),且奇安信默认固定在任务栏;
|
||||
* b. 下载安装微信,固定任务栏(新装任意第三方软件均可),会删除desktop文件
|
||||
* c. 上面两种操作,都会触发任务栏配置更新;通过监控任务栏配置文件,在系统还原过程中,可以明显的看到,在还原1%的时候,配置文件还原到历史文件,桌面图标还原,然后下一秒配置文件就又更新成当前最新的了
|
||||
*/
|
||||
void rsyncAgain();
|
||||
|
||||
/**
|
||||
* @brief 根据场景获取rsync命令参数
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QRegularExpression>
|
||||
#include "../common/utils.h"
|
||||
#include "../common/mydusizetool.h"
|
||||
#include "mymountproxy.h"
|
||||
|
@ -45,6 +46,21 @@ bool UDiskDataBackupProxy::checkEnvEx()
|
|||
return false;
|
||||
}
|
||||
|
||||
// 防命令注入
|
||||
// 1、形如:mkdir '`id&>id_bak_test.txt`'中的文件夹名称
|
||||
// 2、形如:$()的文件夹名称
|
||||
// 3、形如:${}的文件夹名称
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
|
||||
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
|
||||
|
||||
emit checkResult(int(BackupResult::DU_ERR));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString backupPath(m_backupWrapper.m_prefixDestPath);
|
||||
backupPath.replace("//", "/");
|
||||
QStorageInfo udisk(backupPath);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QRegularExpression>
|
||||
#include "../common/utils.h"
|
||||
#include "../common/mydusizetool.h"
|
||||
#include "mymountproxy.h"
|
||||
|
@ -65,6 +66,21 @@ bool UDiskSystemBackupProxy::checkEnvEx()
|
|||
return false;
|
||||
}
|
||||
|
||||
// 防命令注入
|
||||
// 1、形如:mkdir '`id&>id_bak_test.txt`'中的文件夹名称
|
||||
// 2、形如:$()的文件夹名称
|
||||
// 3、形如:${}的文件夹名称
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
if ( m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*`.*`.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
|| m_backupWrapper.m_prefixDestPath.contains(QRegularExpression("[;&|]+"))) {
|
||||
qCritical () << "The path to backup contains ``,$(),${},;&|,etc";
|
||||
|
||||
emit checkResult(int(BackupResult::DU_ERR));
|
||||
return false;
|
||||
}
|
||||
|
||||
QString backupPath(m_backupWrapper.m_prefixDestPath);
|
||||
backupPath.replace("//", "/");
|
||||
QStorageInfo udisk(backupPath);
|
||||
|
@ -293,8 +309,9 @@ QStringList UDiskSystemBackupProxy::getRsyncArgs(UDiskSystemBackupScene scene)
|
|||
args << "--ignore-missing-args";
|
||||
break ;
|
||||
case UDiskSystemBackupScene::MKSQUASHFS :
|
||||
// (在mksquashfs时排除bind挂载的任意一方时,都备份不上)
|
||||
Utils::excludeFstabBindPath(excludes);
|
||||
// --exclude=排除路径设置
|
||||
// -e 排除路径设置
|
||||
for (QString item : m_backupWrapper.m_backupExcludePaths) {
|
||||
if (excludes.contains(item))
|
||||
continue;
|
||||
|
|
|
@ -116,6 +116,9 @@ bool UDiskSystemRestoreProxy::restoreEfi()
|
|||
{
|
||||
qDebug() << "UDiskSystemRestoreProxy::restoreEfi invoke begin";
|
||||
|
||||
// 以读写方式重新挂载boot分区,因为有的机器默认以只读挂载
|
||||
Utils::remountBoot();
|
||||
|
||||
// 是否有/boot/efi目录
|
||||
QString efiPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
efiPath.replace("//", "/");
|
||||
|
@ -124,7 +127,7 @@ bool UDiskSystemRestoreProxy::restoreEfi()
|
|||
repairEfi();
|
||||
|
||||
// 2、重新rw读写挂载
|
||||
remountEfi();
|
||||
Utils::remountEfi();
|
||||
|
||||
// 3、同步efi
|
||||
return rsyncEfi();
|
||||
|
@ -152,34 +155,6 @@ void UDiskSystemRestoreProxy::repairEfi()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载efi分区
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::remountEfi()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载boot分区
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::remountBoot()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
QProcess::execute("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 同步efi
|
||||
*/
|
||||
|
@ -244,7 +219,7 @@ QStringList UDiskSystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
|
|||
args << "--exclude=/data/home";
|
||||
args << "--exclude=/data/root";
|
||||
|
||||
// 云桌面背景路径属于用户数据
|
||||
// 云图片作为桌面背景的路径属于用户数据
|
||||
args << "--exclude=/var/lib/AccountsService";
|
||||
|
||||
// 域用户相关信息,还原后保持不退域
|
||||
|
@ -289,7 +264,7 @@ QStringList UDiskSystemRestoreProxy::getRsyncArgs(SystemRestoreScene scene)
|
|||
args << "--exclude=/usr/bin/rsync";
|
||||
args << "--exclude=/usr/share/rsync";
|
||||
args << "--exclude=/usr/share/initramfs-tools/hooks/kybackup-hooks";
|
||||
args << "--exclude=/usr/share/initramfs-tools/scripts/local-bottom/kybackup";
|
||||
args << "--exclude=/usr/share/initramfs-tools/scripts/*/kybackup";
|
||||
|
||||
// 还原后仍然保持激活状态
|
||||
args << "--exclude=/etc/LICENSE";
|
||||
|
@ -397,9 +372,6 @@ bool UDiskSystemRestoreProxy::doPrepare()
|
|||
} else
|
||||
m_srcPath = m_backupPath;
|
||||
|
||||
// 以读写方式重新挂载boot分区,因为有的机器默认以只读挂载
|
||||
remountBoot();
|
||||
|
||||
qDebug() << "UDiskSystemRestoreProxy::doPrepare invoke end";
|
||||
return true;
|
||||
}
|
||||
|
@ -418,8 +390,10 @@ void UDiskSystemRestoreProxy::restoreSystem()
|
|||
return ;
|
||||
}
|
||||
|
||||
// 停止安全防护
|
||||
QProcess::execute("systemctl stop kysec-init.service");
|
||||
// 停止安全初始化服务,以防过高的CPU占有率,因为还原时安全初始化服务会逐个文件打标记,造成cpu占有率超高系统卡顿
|
||||
Utils::stopKysecInit();
|
||||
// 停止网络服务,以防网络更新
|
||||
Utils::stopNetwork();
|
||||
|
||||
QString destPath = Utils::getSysRootPath();
|
||||
|
||||
|
@ -427,6 +401,7 @@ void UDiskSystemRestoreProxy::restoreSystem()
|
|||
// 自动更新的备份还原时保留用户数据
|
||||
if (m_backupWrapper.m_type == BackupType::RESTORE_SYSTEM_WITH_DATA) {
|
||||
args = getRsyncArgs(SystemRestoreScene::RESTORE_SYSTEM_WITH_DATA);
|
||||
m_bRetainUserData = true;
|
||||
} else {
|
||||
args = getRsyncArgs(SystemRestoreScene::SYSTEM_RESTORE);
|
||||
}
|
||||
|
@ -445,6 +420,15 @@ void UDiskSystemRestoreProxy::restoreSystem()
|
|||
// Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,," + QString::number(m_backupWrapper.m_frontUid));
|
||||
Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,,," + m_backupPoint.m_backupName);
|
||||
|
||||
// 华为9a0等机型设定1分钟后关机重启,原因:运行时还原备份还原工具本身可能会造成运行中的备份还原崩溃,从而无法执行到后面的自动重启代码,故在此预设。
|
||||
// 不再只华为机型使用此方法,将全部机型都改为此方法,缩短操作链
|
||||
// if (Utils::isHuawei990())
|
||||
{
|
||||
QString msg;
|
||||
Utils::executeCMD("shutdown -r +1", msg);
|
||||
qDebug() << msg;
|
||||
}
|
||||
|
||||
Utils::updateSyncFile();
|
||||
Utils::wait(2);
|
||||
QString fileIfSync = Utils::getSysRootPath() + FILE_IF_SYNC;
|
||||
|
@ -471,6 +455,10 @@ void UDiskSystemRestoreProxy::restoreSystem()
|
|||
Utils::wait(5);
|
||||
}
|
||||
|
||||
// 最后,再一次还原home目录以查缺补漏,因为系统还原过程中~/.config等目录中的部分文件可能会更新,会引起部分bug(如任务栏固定图标还原不完整等)
|
||||
this->rsyncAgain();
|
||||
::sync();
|
||||
|
||||
// 2209后新增了一些依赖,还原到以前的4.0.13版后缺少依赖无法运行,故此最后还得还原backup-daemon和kybackup本身
|
||||
// 兼容Qt库从5.12.8升级到5.15,系统还原的最后也将备份还原工具本身还原
|
||||
// QString version = Utils::getBackupVersion();
|
||||
|
@ -478,16 +466,28 @@ void UDiskSystemRestoreProxy::restoreSystem()
|
|||
if (Utils::getSysRootPath() != CASPER_ROOT_PATH)
|
||||
{
|
||||
// initrd.img已经还原为旧状态,需要将新版本的backup-auto-efi等脚本文件更新到initrd.img中,这样我们修改后的新逻辑才能生效
|
||||
// QString msg;
|
||||
// Utils::executeCMD("update-initramfs -u", msg);
|
||||
// qDebug() << msg;
|
||||
|
||||
// 解决bug:182576 【2203自适应升级2309】【2303自适应升级2309】升级成功还原系统失败,应该是有更新包修改了UEFI固件查找引导器文件的引导地址
|
||||
// 故系统还原完成后,重新执行下grub-install命令
|
||||
QString msg;
|
||||
Utils::executeCMD("update-initramfs -u", msg);
|
||||
Utils::executeCMD("grub-install", msg);
|
||||
qDebug() << msg;
|
||||
|
||||
// 写入标记:rsync_backup_self:${UUID}到文件/etc/file_if_sync中,表示需要还原backup-daemon和kybackup本身
|
||||
QString line("rsync_backup_self:");
|
||||
line += m_curUuid;
|
||||
Utils::syncWriteFile(fileIfSync, line);
|
||||
// QString line("rsync_backup_self:");
|
||||
// line += m_curUuid;
|
||||
// Utils::syncWriteFile(fileIfSync, line);
|
||||
// this->undoRestoreData();
|
||||
|
||||
// 加一层保险(因为有些机型上使用"update-initramfs -u"命令会失败,如:华为9006c的2203版等)
|
||||
// QString version = Utils::getBackupVersion();
|
||||
// if (Utils::isHuawei990() && version.contains("4.0.13"))
|
||||
this->rsyncBackupSelf();
|
||||
|
||||
::sync();
|
||||
Utils::wait(5);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,7 +497,7 @@ void UDiskSystemRestoreProxy::restoreSystem()
|
|||
m_isFinished = true;
|
||||
|
||||
if (result) {
|
||||
Utils::wait(2);
|
||||
Utils::wait(3);
|
||||
reboot(RB_AUTOBOOT);
|
||||
}
|
||||
});
|
||||
|
@ -567,4 +567,79 @@ bool UDiskSystemRestoreProxy::checkUdiskExists()
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 再一次同步
|
||||
* @note 意图通过多次同步查缺补漏,如:
|
||||
* 1、因为系统还原过程中~/.config等目录中的部分文件可能会更新,会引起部分bug:
|
||||
* a. 配网,打开奇安信浏览器,触发自动更新(或者软件商店手动更新),且奇安信默认固定在任务栏;
|
||||
* b. 下载安装微信,固定任务栏(新装任意第三方软件均可),会删除desktop文件
|
||||
* c. 上面两种操作,都会触发任务栏配置更新;通过监控任务栏配置文件,在系统还原过程中,可以明显的看到,在还原1%的时候,配置文件还原到历史文件,桌面图标还原,然后下一秒配置文件就又更新成当前最新的了
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::rsyncAgain()
|
||||
{
|
||||
// 保留用户数据还原直接
|
||||
if (m_bRetainUserData)
|
||||
return ;
|
||||
|
||||
QString destPath = Utils::getSysRootPath() + "/home/";
|
||||
destPath.replace("//", "/");
|
||||
Utils::mkpath(destPath);
|
||||
|
||||
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
|
||||
QStringList args;
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/home/";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 未做完的还原,需要在重启后initrd阶段执行备份还原脚本时再进行还原
|
||||
* @note 当前只有备份工具自身未还原
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::undoRestoreData()
|
||||
{
|
||||
QString destPath = Utils::getSysRootPath() + "/var/log/yhkylin-backup-tools/";
|
||||
destPath.replace("//", "/");
|
||||
Utils::mkpath(destPath);
|
||||
|
||||
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
|
||||
QStringList args;
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/backup-daemon";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
|
||||
args.clear();
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/kybackup";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 还原备份还原工具自身
|
||||
* @note 在undoRestoreData基础上增加的一层保险(因为有些机型上使用"update-initramfs -u"命令会失败,如:华为9006c的2203版等)
|
||||
* 本来想在/etc/profile.d/目录或/etc/init.d/目录等下面增加一个.sh脚本文件以开机时自动执行,但试验了几种方式均都未执行,原因未知。
|
||||
*/
|
||||
void UDiskSystemRestoreProxy::rsyncBackupSelf()
|
||||
{
|
||||
QString destPath = Utils::getSysRootPath() + "/usr/bin/";
|
||||
destPath.replace("//", "/");
|
||||
Utils::mkpath(destPath);
|
||||
|
||||
RsyncPathToDirProcess * process = new RsyncPathToDirProcess(this);
|
||||
QStringList args;
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/kybackup";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
|
||||
args.clear();
|
||||
args << "-avAHXr";
|
||||
args << m_srcPath + "/usr/bin/backup-daemon";
|
||||
args << destPath;
|
||||
process->start(args);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,10 +35,6 @@ private:
|
|||
bool restoreEfi();
|
||||
// 修复efi目录
|
||||
void repairEfi();
|
||||
// 以读写方式重新挂载efi分区
|
||||
void remountEfi();
|
||||
// 以读写方式重新挂载boot分区
|
||||
void remountBoot();
|
||||
// 同步efi
|
||||
bool rsyncEfi();
|
||||
// 系统还原
|
||||
|
@ -47,6 +43,20 @@ private:
|
|||
bool doPrepare();
|
||||
// 异机还原时更新grub.cfg中的分区UUID
|
||||
void updateGrubUUid();
|
||||
// 待还原数据
|
||||
void undoRestoreData();
|
||||
// 还原备份还原工具自身
|
||||
void rsyncBackupSelf();
|
||||
|
||||
/**
|
||||
* @brief 再一次同步
|
||||
* @note 意图通过多次同步查缺补漏,如:
|
||||
* 1、因为系统还原过程中~/.config等目录中的部分文件可能会更新,会引起部分bug:
|
||||
* a. 配网,打开奇安信浏览器,触发自动更新(或者软件商店手动更新),且奇安信默认固定在任务栏;
|
||||
* b. 下载安装微信,固定任务栏(新装任意第三方软件均可),会删除desktop文件
|
||||
* c. 上面两种操作,都会触发任务栏配置更新;通过监控任务栏配置文件,在系统还原过程中,可以明显的看到,在还原1%的时候,配置文件还原到历史文件,桌面图标还原,然后下一秒配置文件就又更新成当前最新的了
|
||||
*/
|
||||
void rsyncAgain();
|
||||
|
||||
/**
|
||||
* @brief 根据场景获取rsync命令参数
|
||||
|
@ -74,6 +84,8 @@ private:
|
|||
ParseBackupList::BackupPoint m_backupPoint;
|
||||
// 强制结束标志(stop后没反应的情况,系统处于睡眠状态)
|
||||
bool m_isForce;
|
||||
// 是否保留用户数据
|
||||
bool m_bRetainUserData = false;
|
||||
};
|
||||
|
||||
#endif // UDISKSYSTEMRESTOREPROXY_H
|
||||
|
|
|
@ -758,7 +758,8 @@ bool Utils::writeBackupLog(QString line)
|
|||
*/
|
||||
bool Utils::syncWriteFile(const QString &fileName, const QString& content)
|
||||
{
|
||||
std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(std::fopen(fileName.toStdString().data(), "a+"), std::fclose);
|
||||
qDebug() << fileName << content;
|
||||
std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(std::fopen(fileName.toStdString().data(), "w"), std::fclose);
|
||||
|
||||
if (!fp) {
|
||||
std::perror("file opening failed!");
|
||||
|
@ -1521,3 +1522,49 @@ QString Utils::getBackupVersion()
|
|||
return version;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载efi分区
|
||||
*/
|
||||
void Utils::remountEfi()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot/efi";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
Utils::executeCmd("mount", args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载boot分区
|
||||
*/
|
||||
void Utils::remountBoot()
|
||||
{
|
||||
QString mountPath = Utils::getSysRootPath() + "/boot";
|
||||
mountPath.replace("//", "/");
|
||||
QStringList args;
|
||||
args << "-o"
|
||||
<< "rw,remount"
|
||||
<< mountPath;
|
||||
Utils::executeCmd("mount", args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 停掉安全初始化服务
|
||||
*/
|
||||
void Utils::stopKysecInit()
|
||||
{
|
||||
Utils::executeCmd("systemctl stop kysec-init.service");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停掉网络服务
|
||||
*/
|
||||
void Utils::stopNetwork()
|
||||
{
|
||||
Utils::executeCmd("service network-manager stop");
|
||||
}
|
||||
|
||||
|
|
|
@ -401,6 +401,26 @@ public:
|
|||
*/
|
||||
static QString getBackupVersion();
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载efi分区
|
||||
*/
|
||||
static void remountEfi();
|
||||
|
||||
/**
|
||||
* @brief 重新rw读写挂载boot分区
|
||||
*/
|
||||
static void remountBoot();
|
||||
|
||||
/**
|
||||
* @brief 停掉安全初始化服务
|
||||
*/
|
||||
static void stopKysecInit();
|
||||
|
||||
/**
|
||||
* @brief 停掉网络服务
|
||||
*/
|
||||
static void stopNetwork();
|
||||
|
||||
/**
|
||||
* @brief 设置日志文件
|
||||
* @param logfile
|
||||
|
|
|
@ -78,10 +78,7 @@ Or click "Update Backup" button, pop up data backup list window. As shown in fig
|
|||
![Fig 15 data backup list -big](image/15.png)
|
||||
|
||||
Then, click "Next" button, enter backup checking page --> backup preparing --> backuping --> backup finished. Such as system backup.
|
||||
|
||||
|
||||
- **Update Data Backup** -- On the basis of a data backup, update the backup data.
|
||||
|
||||
- **Data Recovery** -- Recovery the data to its previous backup state, and the function is similar to system restore.
|
||||
|
||||
![Fig 16 Data recovery-big](image/16.png)
|
||||
|
|
|
@ -78,9 +78,7 @@
|
|||
|
||||
选择好备份路径后,单击“下一步”按钮,进入环境检测-->备份准备-->备份中-->备份完成等环节,和系统备份类似。
|
||||
数据备份首页右下角的“备份管理”,可用来查看数据备份状态,删除无效备份。
|
||||
|
||||
- **数据增量备份** —— 在某个数据备份的基础上,更新备份点的数据。
|
||||
|
||||
- **数据还原** —— 还原到某个数据备份的状态,功能与系统还原相似。
|
||||
|
||||
![图 16 数据还原主界面-big](image/16.png)
|
||||
|
@ -147,7 +145,6 @@ Tips:如果制作镜像文件时带有数据分区,则在下一步“安装
|
|||
## 常见问题
|
||||
- 无法使用备份还原
|
||||
在安装操作系统时,必须要选中“创建备份还原分区”,备份还原才能使用。
|
||||
|
||||
- 备份分区空间不足
|
||||
备份分区(/backup)大小是安装系统时固定的,一般也不会太大,随着系统的使用量逐渐增大,会造成备份空间不足无法进行备份的情况。此时可以备份到移动设备上,不过备份速度会变慢。
|
||||
建议系统只进行一个初装备份到备份分区,后面的系统备份都备份到移动设备上。比较重要的数据统一放到某个目录中,用数据备份功能进行备份。
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
yhkylin-backup-tools (4.1.0.1-ok7) v101; urgency=medium
|
||||
|
||||
* BUG :【备份还原】切换至平板模式时,窗口没有最大化
|
||||
【备份还原】窗口选项菜单未翻译成中文
|
||||
【备份还原】菜单-退出按钮显示Exit,预期显示退出
|
||||
【备份还原】gurb备份/还原系统时,显示乱码
|
||||
* 需求号:无
|
||||
* 其它改动:无
|
||||
* 其它影响域:无
|
||||
|
||||
-- lidecheng <lidecheng@kylinos.cn> Mon, 04 Sep 2023 18:03:27 +0800
|
||||
|
||||
yhkylin-backup-tools (4.1.0.1-ok6) yangtze; urgency=medium
|
||||
|
||||
* BUG :【备份还原】【次要】删除备份成功的弹窗,关闭按钮无悬浮提示
|
||||
|
|
|
@ -180,6 +180,7 @@ void BackupPointListDialog::keyPressEvent(QKeyEvent* event)
|
|||
{
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Escape:
|
||||
this->close();
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Left:
|
||||
|
|
|
@ -315,17 +315,17 @@ bool BackupListWidget::checkPathLimit(const QString &path)
|
|||
// 2、形如:$()的文件夹名称
|
||||
// 3、形如:${}的文件夹名称
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
// if ( path.contains(QRegularExpression(".*`.*`.*"))
|
||||
// || path.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
// || path.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
// || path.contains(QRegularExpression("[;&|]+"))) {
|
||||
// MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
|
||||
// return false;
|
||||
// }
|
||||
if ( path.contains(QRegularExpression(".*`.*`.*"))
|
||||
|| path.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
|| path.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
|| path.contains(QRegularExpression("[;&|]+"))) {
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1、列表中是否已经存在
|
||||
if (contains(path)) {
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Warning"),
|
||||
QObject::tr("Path already exists : ") + path,
|
||||
QObject::tr("OK"));
|
||||
return false;
|
||||
|
@ -334,7 +334,7 @@ bool BackupListWidget::checkPathLimit(const QString &path)
|
|||
// 2、路径是否存在
|
||||
QFileInfo fileInfo(path);
|
||||
if (!fileInfo.exists()) {
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Warning"),
|
||||
QObject::tr("The file or directory does not exist : ") + path,
|
||||
QObject::tr("OK"));
|
||||
return false;
|
||||
|
@ -343,8 +343,9 @@ bool BackupListWidget::checkPathLimit(const QString &path)
|
|||
// 3、是否是限定路径及其子路径
|
||||
bool blimit = false;
|
||||
QString dirCanBeSelected;
|
||||
QString abstractPath = fileInfo.absoluteFilePath();
|
||||
for (const QString &item : m_pathLimit) {
|
||||
if (path.startsWith(item)) {
|
||||
if (abstractPath.startsWith(item)) {
|
||||
blimit = true;
|
||||
break;
|
||||
}
|
||||
|
@ -357,7 +358,7 @@ bool BackupListWidget::checkPathLimit(const QString &path)
|
|||
}
|
||||
}
|
||||
if (m_pathLimit.size() > 0 && !blimit) {
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Warning"),
|
||||
QObject::tr("Only data that exists in the follow directorys can be selected: %1.\n Path:%2 is not in them.").arg(dirCanBeSelected).arg(path),
|
||||
QObject::tr("OK"));
|
||||
return false;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "backuppositionselectdialog.h"
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include "filefilterproxymodelforbackup.h"
|
||||
#include "../../common/utils.h"
|
||||
#include "../messageboxutils.h"
|
||||
|
||||
BackupPositionSelectDialog::BackupPositionSelectDialog(QWidget* parent) :
|
||||
QFileDialog(parent)
|
||||
|
@ -8,19 +12,85 @@ BackupPositionSelectDialog::BackupPositionSelectDialog(QWidget* parent) :
|
|||
setWindowTitle(tr("Please select a path"));
|
||||
setViewMode(QFileDialog::Detail);
|
||||
setFileMode(QFileDialog::DirectoryOnly);
|
||||
setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
QList<QUrl> siderUrls;
|
||||
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath());
|
||||
siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath() + "/data");
|
||||
QList<QString> localDisks = Utils::getLocalDisks();
|
||||
for (const QString& path: localDisks) {
|
||||
siderUrls << QUrl::fromLocalFile(path);
|
||||
}
|
||||
setSidebarUrls(siderUrls);
|
||||
FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
|
||||
setProxyModel(proxy);
|
||||
// 主题和文管重构了QFileDialog,下面代码已经失效
|
||||
// setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
// QList<QUrl> siderUrls;
|
||||
// siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath());
|
||||
// siderUrls << QUrl::fromLocalFile(Utils::getSysRootPath() + "/data");
|
||||
// QList<QString> localDisks = Utils::getLocalDisks();
|
||||
// for (const QString& path: localDisks) {
|
||||
// siderUrls << QUrl::fromLocalFile(path);
|
||||
// }
|
||||
// setSidebarUrls(siderUrls);
|
||||
// FileFilterProxyModeForBackup *proxy = new FileFilterProxyModeForBackup;
|
||||
// setProxyModel(proxy);
|
||||
}
|
||||
|
||||
BackupPositionSelectDialog::~BackupPositionSelectDialog()
|
||||
{}
|
||||
|
||||
bool BackupPositionSelectDialog::checkSelectedFiles()
|
||||
{
|
||||
QStringList selectFiles = selectedFiles();
|
||||
for (const QString & fileName : selectFiles) {
|
||||
// 防命令注入
|
||||
// 1、形如:mkdir '`id&>id_bak_test.txt`'中的文件夹名称
|
||||
// 2、形如:$()的文件夹名称
|
||||
// 3、形如:${}的文件夹名称
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
if ( fileName.contains(QRegularExpression(".*`.*`.*"))
|
||||
|| fileName.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
|| fileName.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
|| fileName.contains(QRegularExpression("[;&|]+"))) {
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 主题重新实现了QFileDialog后很多功能已经丢失(如:文件夹过滤等),需要再次进行过滤,真难用
|
||||
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
|
||||
backupPath.replace("//", "/");
|
||||
if (fileName == backupPath || fileName.contains(BACKUP_SNAPSHOTS_PATH)) {
|
||||
// 不能嵌套备份,请选择其它目录
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
|
||||
QObject::tr("Cannot nest backups, please select another directory."),
|
||||
QObject::tr("OK"));
|
||||
return false;
|
||||
} else if (fileName.endsWith(BACKUP_PATH)) {
|
||||
QString subfile = fileName + "/snapshots";
|
||||
if (Utils::isDirExist(subfile)) {
|
||||
// 不能嵌套备份,请选择其它目录
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
|
||||
QObject::tr("Cannot nest backups, please select another directory."),
|
||||
QObject::tr("OK"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BackupPositionSelectDialog::goAccept()
|
||||
{
|
||||
if (checkSelectedFiles())
|
||||
accept();
|
||||
}
|
||||
|
||||
// 主题和文管重构了QFileDialog,需要使用下面代码绑定accept信号
|
||||
void BackupPositionSelectDialog::showEvent(QShowEvent* event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
if (this->isVisible()) {
|
||||
for (QWidget* widget : this->findChildren<QWidget*>()) {
|
||||
if (widget->objectName() == "acceptButton") {
|
||||
QPushButton * btn = qobject_cast<QPushButton*>(widget);
|
||||
disconnect(btn, &QPushButton::clicked, 0, 0);
|
||||
connect(btn, &QPushButton::clicked, [=](bool checked){
|
||||
Q_UNUSED(checked)
|
||||
this->goAccept();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@ class BackupPositionSelectDialog : public QFileDialog {
|
|||
public:
|
||||
explicit BackupPositionSelectDialog(QWidget* parent = nullptr);
|
||||
virtual ~BackupPositionSelectDialog();
|
||||
|
||||
bool checkSelectedFiles();
|
||||
public slots:
|
||||
void goAccept();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* event) override;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,17 +20,17 @@ bool FileFilterProxyModeForBackup::filterAcceptsRow(int sourceRow, const QModelI
|
|||
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;
|
||||
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);
|
||||
if (fileName == "backup") {
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include "filefilterproxymodelforbackup.h"
|
||||
#include "../messageboxutils.h"
|
||||
|
||||
MyFileSelect::MyFileSelect(QWidget* parent) :
|
||||
QFileDialog(parent)
|
||||
{
|
||||
this->setFileMode(QFileDialog::ExistingFiles);
|
||||
// sdk和文管重构了QFileDialog,下面代码已经失效
|
||||
// 主题和文管重构了QFileDialog,下面代码已经失效
|
||||
/*
|
||||
this->setViewMode(QFileDialog::Detail);
|
||||
this->setFilter(QDir::System | QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
|
@ -27,15 +28,37 @@ MyFileSelect::MyFileSelect(QWidget* parent) :
|
|||
*/
|
||||
}
|
||||
|
||||
bool MyFileSelect::checkSelectedFiles()
|
||||
{
|
||||
QStringList selectFiles = selectedFiles();
|
||||
for (const QString & fileName : selectFiles) {
|
||||
// 防命令注入
|
||||
// 1、形如:mkdir '`id&>id_bak_test.txt`'中的文件夹名称
|
||||
// 2、形如:$()的文件夹名称
|
||||
// 3、形如:${}的文件夹名称
|
||||
// 4、包含[;、&、|]等可以包含并执行系统命令或用于连续执行系统命令的符号
|
||||
if ( fileName.contains(QRegularExpression(".*`.*`.*"))
|
||||
|| fileName.contains(QRegularExpression(".*\\$\\(.*\\).*"))
|
||||
|| fileName.contains(QRegularExpression(".*\\$\\{.*\\}.*"))
|
||||
|| fileName.contains(QRegularExpression("[;&|]+"))) {
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"), QObject::tr("Path can not include symbols that such as : ``,$(),${},;,&,|,etc."), QObject::tr("OK"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MyFileSelect::goAccept()
|
||||
{
|
||||
accept();
|
||||
if (checkSelectedFiles())
|
||||
accept();
|
||||
}
|
||||
|
||||
MyFileSelect::~MyFileSelect()
|
||||
{}
|
||||
|
||||
// sdk和文管重构了QFileDialog,需要使用下面代码绑定accept信号
|
||||
// 主题和文管重构了QFileDialog,需要使用下面代码绑定accept信号
|
||||
void MyFileSelect::showEvent(QShowEvent* event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
|
|
@ -9,6 +9,7 @@ public:
|
|||
explicit MyFileSelect(QWidget* parent = nullptr);
|
||||
virtual ~MyFileSelect();
|
||||
|
||||
bool checkSelectedFiles();
|
||||
public slots:
|
||||
void goAccept();
|
||||
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPainter>
|
||||
#include <ukuistylehelper/ukuistylehelper.h>
|
||||
#include <windowmanager/windowmanager.h>
|
||||
#include <unistd.h>
|
||||
#include "globalbackupinfo.h"
|
||||
#include "../common/mydefine.h"
|
||||
#include "../common/utils.h"
|
||||
#include "messageboxutils.h"
|
||||
#include <ukuistylehelper/ukuistylehelper.h>
|
||||
#include <windowmanager/windowmanager.h>
|
||||
|
||||
DeleteBackupDialog::DeleteBackupDialog(ParseBackupList::BackupPoint backupPonit, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#! /bin/bash
|
||||
|
||||
ts_file_list=(`ls *.ts`)
|
||||
|
||||
for ts in "${ts_file_list[@]}"
|
||||
do
|
||||
lrelease "${ts}"
|
||||
done
|
||||
|
||||
mv *.qm resource/language/
|
|
@ -146,14 +146,20 @@ FORMS += \
|
|||
OTHER_FILES +=
|
||||
|
||||
TRANSLATIONS += qt_zh_CN.ts \
|
||||
qt_bo_CN.ts
|
||||
qt_bo_CN.ts \
|
||||
qt_mn_MN.ts \
|
||||
qt_zh_HK.ts
|
||||
|
||||
system(rm -f qt_zh_CN.qm)
|
||||
!system(lrelease qt_zh_CN.ts): error("Failed to generate cp qt_zh_CN.qm")
|
||||
system(cp qt_zh_CN.qm resource/language/)
|
||||
system(rm -f qt_bo_CN.qm)
|
||||
!system(lrelease qt_bo_CN.ts): error("Failed to generate qt_bo_CN.qm")
|
||||
system(cp qt_bo_CN.qm resource/language/)
|
||||
message($$system(./generate_translations_qm.sh))
|
||||
#system(rm -f qt_zh_CN.qm)
|
||||
#!system(lrelease qt_zh_CN.ts): error("Failed to generate cp qt_zh_CN.qm")
|
||||
#system(cp qt_zh_CN.qm resource/language/)
|
||||
#system(rm -f qt_bo_CN.qm)
|
||||
#!system(lrelease qt_bo_CN.ts): error("Failed to generate qt_bo_CN.qm")
|
||||
#system(cp qt_bo_CN.qm resource/language/)
|
||||
#system(rm -f qt_mn_MN.qm)
|
||||
#!system(lrelease qt_mn_MN.ts): error("Failed to generate qt_mn_MN.qm")
|
||||
#system(cp qt_mn_MN.qm resource/language/)
|
||||
|
||||
RESOURCES += \
|
||||
app.qrc
|
||||
|
|
|
@ -57,16 +57,17 @@ int main(int argc, char *argv[])
|
|||
GlobelBackupInfo::instance().setIsWayland(true);
|
||||
}
|
||||
MainDialog w;
|
||||
// 居中窗口
|
||||
centerToScreen(&w);
|
||||
a.setWindowIcon(QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS, QIcon(":/images/yhkylin-backup-tools.png")));
|
||||
a.setActivationWindow(&w, true);
|
||||
a.setApplicationName(QObject::tr("Backup & Restore"));
|
||||
a.setApplicationVersion("4.1.0.0-0k17.18");
|
||||
|
||||
//如果是第一个实例,则绑定,方便下次调用
|
||||
QObject::connect(&a,SIGNAL(messageReceived(const QString&)),&w,SLOT(sltMessageReceived(const QString&)));
|
||||
|
||||
w.show();
|
||||
// 居中窗口
|
||||
centerToScreen(&w);
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
|
@ -82,53 +83,70 @@ void initApp(QApplication& a)
|
|||
|
||||
// 区分中英文
|
||||
QString locale = QLocale::system().name();
|
||||
|
||||
// QT自身标准的翻译
|
||||
#ifndef QT_NO_TRANSLATION
|
||||
QString translatorFileName = QLatin1String("qt_");
|
||||
translatorFileName += locale;
|
||||
QTranslator *selfTransOfQt = new QTranslator();
|
||||
if (selfTransOfQt->load(translatorFileName, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
if (selfTransOfQt->load(QLocale(), QString("qt"), QString("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
a.installTranslator(selfTransOfQt);
|
||||
else
|
||||
qDebug() << "load qt translator file failed!";
|
||||
#endif
|
||||
|
||||
// 应用内的翻译
|
||||
QTranslator *translator = new QTranslator();
|
||||
if (locale == "zh_CN") {
|
||||
//中文需要翻译
|
||||
if (!translator->load(":/language/qt_zh_CN.qm")) //qtcreator启动后看到在资源目录下
|
||||
qDebug() << "load translator file failed!";
|
||||
else
|
||||
a.installTranslator(translator);
|
||||
} else if (locale == "bo_CN") {
|
||||
//藏文需要翻译
|
||||
if (!translator->load(":/language/qt_bo_CN.qm")) //qtcreator启动后看到在资源目录下
|
||||
qDebug() << "load translator file failed!";
|
||||
else
|
||||
a.installTranslator(translator);
|
||||
}
|
||||
|
||||
// 部分sdk控件用到翻译文件
|
||||
QTranslator *transGui = new QTranslator();
|
||||
if (locale == "zh_CN")
|
||||
{
|
||||
if(transGui->load(":/translations/gui_zh_CN.qm"))
|
||||
if (locale == "zh_CN") {
|
||||
if (transGui->load(":/translations/gui_zh_CN.qm"))
|
||||
{
|
||||
a.installTranslator(transGui);
|
||||
}
|
||||
} else if (locale == "bo_CN")
|
||||
{
|
||||
if(transGui->load(":/translations/gui_bo_CN.qm"))
|
||||
} else if (locale == "bo_CN") {
|
||||
if (transGui->load(":/translations/gui_bo_CN.qm"))
|
||||
{
|
||||
a.installTranslator(transGui);
|
||||
}
|
||||
} else if (locale == "mn_MN" || locale == "mn") {
|
||||
if (transGui->load(":/translations/gui_mn.qm")) {
|
||||
a.installTranslator(transGui);
|
||||
}
|
||||
} else if (locale == "zh_HK") {
|
||||
if(transGui->load(":/translations/gui_zh_HK.qm")) {
|
||||
a.installTranslator(transGui);
|
||||
}
|
||||
}
|
||||
|
||||
// 命令行参数
|
||||
QCoreApplication::setApplicationName(QObject::tr("kybackup"));
|
||||
QCoreApplication::setApplicationVersion("4.0.14");
|
||||
// 应用内的翻译
|
||||
QTranslator *translator = new QTranslator();
|
||||
QString translatorResourceName(":/language/qt_");
|
||||
translatorResourceName += locale;
|
||||
translatorResourceName += ".qm";
|
||||
if (!translator->load(translatorResourceName)) //qtcreator启动后看到在资源目录下
|
||||
qDebug() << translatorResourceName << "load translator file failed!";
|
||||
else {
|
||||
a.installTranslator(translator);
|
||||
qDebug() << translatorResourceName << "load translator file success!";
|
||||
}
|
||||
// if (locale == "zh_CN") {
|
||||
// //中文需要翻译
|
||||
// if (!translator->load(":/language/qt_zh_CN.qm")) //qtcreator启动后看到在资源目录下
|
||||
// qDebug() << "load translator file failed!";
|
||||
// else
|
||||
// a.installTranslator(translator);
|
||||
// } else if (locale == "bo_CN") {
|
||||
// //藏文需要翻译
|
||||
// if (!translator->load(":/language/qt_bo_CN.qm")) //qtcreator启动后看到在资源目录下
|
||||
// qDebug() << "load translator file failed!";
|
||||
// else
|
||||
// a.installTranslator(translator);
|
||||
// } else if (locale == "mn_MN") {
|
||||
// //蒙古文需要翻译
|
||||
// if (!translator->load(":/language/qt_mn_MN.qm")) //qtcreator启动后看到在资源目录下
|
||||
// qDebug() << "load translator file failed!";
|
||||
// else
|
||||
// a.installTranslator(translator);
|
||||
// }
|
||||
|
||||
// 命令行参数
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("kybackup helper");
|
||||
parser.addHelpOption();
|
||||
|
@ -219,7 +237,6 @@ void centerToScreen(QWidget* widget)
|
|||
{
|
||||
if (!widget)
|
||||
return;
|
||||
|
||||
int x = widget->width();
|
||||
int y = widget->height();
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "aboutdialog.h"
|
||||
#include "gsettingswrapper.h"
|
||||
#include "component/mywidget.h"
|
||||
#include "../common/dynamiccreator.h"
|
||||
|
||||
MainDialog::MainDialog(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
|
@ -126,7 +125,7 @@ void MainDialog::initTileBar()
|
|||
m_maxBtn = new QPushButton;
|
||||
m_closeBtn = new QPushButton;
|
||||
|
||||
m_menuOptionBtn->setToolTip(tr("Main menu"));
|
||||
m_menuOptionBtn->setToolTip(tr("Options"));
|
||||
m_minBtn->setToolTip(tr("Minimize"));
|
||||
m_maxBtn->setToolTip(tr("Maximize"));
|
||||
m_closeBtn->setToolTip(tr("Close"));
|
||||
|
@ -179,7 +178,7 @@ void MainDialog::initTileBar()
|
|||
backupMain->addAction(m_backupHelp);
|
||||
m_backupAbout = new QAction(tr("About"), m_titleWidget);
|
||||
backupMain->addAction(m_backupAbout);
|
||||
m_backupExit = new QAction(tr("Exit"), m_titleWidget);
|
||||
m_backupExit = new QAction(tr("Quit"), m_titleWidget);
|
||||
backupMain->addAction(m_backupExit);
|
||||
|
||||
m_titleLayout->addStretch();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../common/mydefine.h"
|
||||
#include "globalsignals.h"
|
||||
#include "globalbackupinfo.h"
|
||||
#include <QPushButton>
|
||||
|
||||
|
||||
MyMessageBox::MyMessageBox(QWidget *parent) :
|
||||
|
@ -48,8 +49,8 @@ void MessageBoxUtils::QMESSAGE_BOX_INFORMATION(QWidget* q_parent, const QString&
|
|||
box->setMsgIcon(QMessageBox::Information);
|
||||
box->setWindowTitle(typelabel);
|
||||
box->setText(message);
|
||||
box->setStandardButtons(QMessageBox::Ok);
|
||||
box->setButtonText(QMessageBox::Ok, label);
|
||||
QPushButton * okbtn = box->addButton(label, QMessageBox::AcceptRole);
|
||||
box->setDefaultButton(okbtn);
|
||||
box->exec();
|
||||
}
|
||||
|
||||
|
@ -59,8 +60,8 @@ void MessageBoxUtils::QMESSAGE_BOX_WARNING(QWidget* q_parent, const QString& typ
|
|||
box->setMsgIcon(QMessageBox::Warning);
|
||||
box->setWindowTitle(typelabel);
|
||||
box->setText(message);
|
||||
box->setStandardButtons(QMessageBox::Ok);
|
||||
box->setButtonText(QMessageBox::Ok, label);
|
||||
QPushButton * okbtn = box->addButton(label, QMessageBox::AcceptRole);
|
||||
box->setDefaultButton(okbtn);
|
||||
box->exec();
|
||||
}
|
||||
|
||||
|
@ -70,10 +71,11 @@ bool MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(QWidget *q_parent, const QStri
|
|||
box->setMsgIcon(QMessageBox::Question);
|
||||
box->setWindowTitle(typelabel);
|
||||
box->setText(message);
|
||||
box->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||
box->setButtonText(QMessageBox::Ok, label_yes);
|
||||
box->setButtonText(QMessageBox::Cancel, label_no);
|
||||
if (box->exec() != QMessageBox::Ok) {
|
||||
QPushButton * okbtn = box->addButton(label_yes, QMessageBox::AcceptRole);
|
||||
box->addButton(label_no, QMessageBox::RejectRole);
|
||||
box->setDefaultButton(okbtn);
|
||||
box->exec();
|
||||
if (box->clickedButton() != okbtn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -86,7 +88,7 @@ void MessageBoxUtils::QMESSAGE_BOX_CRITICAL(QWidget* q_parent, const QString& ty
|
|||
box->setMsgIcon(QMessageBox::Critical);
|
||||
box->setWindowTitle(typelabel);
|
||||
box->setText(message);
|
||||
box->setStandardButtons(QMessageBox::Ok);
|
||||
box->setButtonText(QMessageBox::Ok, label);
|
||||
QPushButton * okbtn = box->addButton(label, QMessageBox::AcceptRole);
|
||||
box->setDefaultButton(okbtn);
|
||||
box->exec();
|
||||
}
|
||||
|
|
|
@ -50,13 +50,13 @@ DataBackup::DataBackup(QWidget *parent /*= nullptr*/) :
|
|||
m_pInterface(nullptr)
|
||||
{
|
||||
// 界面手写代码创建,作为练手
|
||||
initFirstWidget();
|
||||
initSecondWidget();
|
||||
initSecondWidget_inc();
|
||||
initThirdWidget();
|
||||
initForthWidget();
|
||||
initFifthWidget();
|
||||
initLastWidget();
|
||||
initHomePage();
|
||||
initSetBackupPathsPage();
|
||||
initSetIncPathsPage();
|
||||
initCheckPage();
|
||||
initNameBackupPage();
|
||||
initBackupingPage();
|
||||
initLastPage();
|
||||
}
|
||||
|
||||
DataBackup::~DataBackup()
|
||||
|
@ -71,7 +71,7 @@ DataBackup::~DataBackup()
|
|||
/**
|
||||
* @brief 初始化第一个页面
|
||||
*/
|
||||
void DataBackup::initFirstWidget()
|
||||
void DataBackup::initHomePage()
|
||||
{
|
||||
QWidget *homePage = new QWidget;
|
||||
QVBoxLayout *vLayout = new QVBoxLayout;
|
||||
|
@ -225,6 +225,7 @@ void DataBackup::initFirstWidget()
|
|||
backupPointManage->setProperty("useButtonPalette", true);
|
||||
QPalette pal(backupPointManage->palette());
|
||||
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Text, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Button, this->palette().base().color());
|
||||
backupPointManage->setPalette(pal);
|
||||
bottomHBoxLayout->addWidget(backupPointManage);
|
||||
|
@ -243,15 +244,19 @@ void DataBackup::initFirstWidget()
|
|||
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::styleNameChanged, this, [=](bool isDark) {
|
||||
Q_UNUSED(isDark)
|
||||
// 深浅主题切换时,因为调色板已经更换,高亮等颜色已经改变,所以要重新加载图标。
|
||||
// from席博文:因为按钮的文字颜色换了一个类型,因为设计非要什么半透明透明效果的;Text就是半透明的,buttontext就是不半透明。所以将ButtonText改为Text
|
||||
QPalette pal(backupPointManage->palette());
|
||||
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Text, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Button, this->palette().base().color());
|
||||
backupPointManage->setPalette(pal);
|
||||
});
|
||||
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::themeColorChanged, this, [=]() {
|
||||
// 强调色更换,高亮等颜色已经改变,所以要重新加载图标。
|
||||
// from席博文:因为按钮的文字颜色换了一个类型,因为设计非要什么半透明透明效果的;Text就是半透明的,buttontext就是不半透明。所以将ButtonText改为Text
|
||||
QPalette pal(backupPointManage->palette());
|
||||
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Text, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Button, this->palette().base().color());
|
||||
backupPointManage->setPalette(pal);
|
||||
});
|
||||
|
@ -288,7 +293,7 @@ void DataBackup::on_next_clicked(bool checked)
|
|||
/**
|
||||
* @brief 初始化第二个页面(新建备份)
|
||||
*/
|
||||
void DataBackup::initSecondWidget()
|
||||
void DataBackup::initSetBackupPathsPage()
|
||||
{
|
||||
QWidget *selectPathPage = new QWidget;
|
||||
|
||||
|
@ -515,25 +520,7 @@ void DataBackup::initSecondWidget()
|
|||
if (!selectFiles.isEmpty()) {
|
||||
QString fileName = selectFiles.at(0);
|
||||
|
||||
// sdk重新实现了QFileDialog后很多功能已经丢失(如:文件夹过滤等),需要再次进行过滤,真难用
|
||||
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
|
||||
backupPath.replace("//", "/");
|
||||
if (fileName == backupPath || fileName.contains(BACKUP_SNAPSHOTS_PATH)) {
|
||||
// 不能嵌套备份,请选择其它目录
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
|
||||
QObject::tr("Cannot nest backups, please select another directory."),
|
||||
QObject::tr("OK"));
|
||||
return ;
|
||||
} else if (fileName.endsWith(BACKUP_PATH)) {
|
||||
QString subfile = fileName + "/snapshots";
|
||||
if (Utils::isDirExist(subfile)) {
|
||||
// 不能嵌套备份,请选择其它目录
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
|
||||
QObject::tr("Cannot nest backups, please select another directory."),
|
||||
QObject::tr("OK"));
|
||||
return ;
|
||||
}
|
||||
} else if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
|
||||
if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
|
||||
// 选择了移动设备挂载目录的子孙目录
|
||||
// 移动设备只能选择挂载目录本身
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
|
||||
|
@ -671,7 +658,7 @@ void DataBackup::getPathsLimit(QStringList &pathLimits, QList<QUrl> &siderUrls)
|
|||
/**
|
||||
* @brief 初始化第二个页面(增量备份)
|
||||
*/
|
||||
void DataBackup::initSecondWidget_inc()
|
||||
void DataBackup::initSetIncPathsPage()
|
||||
{
|
||||
QWidget *incSelectPathPage = new QWidget;
|
||||
|
||||
|
@ -935,9 +922,9 @@ void DataBackup::addOldBackupPaths(BackupListWidget *listWidget)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第三个页面
|
||||
* @brief 初始化检测页面
|
||||
*/
|
||||
void DataBackup::initThirdWidget()
|
||||
void DataBackup::initCheckPage()
|
||||
{
|
||||
QWidget *checkPage = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
@ -1335,10 +1322,10 @@ void DataBackup::on_checkEnv_end(int result)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第四个页面
|
||||
* @brief 初始化备份命名页面
|
||||
*/
|
||||
#define MAX_LEN_BACKUPNAME 64
|
||||
void DataBackup::initForthWidget()
|
||||
void DataBackup::initNameBackupPage()
|
||||
{
|
||||
QWidget *nameBackupPage = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
@ -1616,9 +1603,9 @@ bool DataBackup::isExistsBackupName(const QString & backupName)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 第五个页面
|
||||
* @brief 初始化备份中页面
|
||||
*/
|
||||
void DataBackup::initFifthWidget()
|
||||
void DataBackup::initBackupingPage()
|
||||
{
|
||||
QWidget *backupingPage = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
@ -1669,7 +1656,6 @@ void DataBackup::initFifthWidget()
|
|||
hlayoutTopLine2->addWidget(label4);
|
||||
hlayoutTopLine2->addSpacing(11);
|
||||
vlayout->addLayout(hlayoutTopLine2);
|
||||
|
||||
vlayout->addSpacing(80);
|
||||
|
||||
// ------------ 中部布局begin-------------
|
||||
|
@ -1706,8 +1692,8 @@ void DataBackup::initFifthWidget()
|
|||
hlayoutCenterFont2->addStretch();
|
||||
hlayoutCenterFont2->setAlignment(Qt::AlignCenter);
|
||||
vlayout->addLayout(hlayoutCenterFont2);
|
||||
|
||||
vlayout->addSpacing(56);
|
||||
|
||||
// 第三行
|
||||
QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
|
||||
// 取消按钮
|
||||
|
@ -1737,6 +1723,10 @@ void DataBackup::initFifthWidget()
|
|||
// 不要使用电脑,以防数据丢失
|
||||
labelTip->setDeplayText(tr("Do not use computer in case of data loss"));
|
||||
cancel->setEnabled(true);
|
||||
if (this->m_isIncrement)
|
||||
cancel->setVisible(false);
|
||||
else
|
||||
cancel->setVisible(true);
|
||||
|
||||
// 开始备份
|
||||
this->on_backup_start();
|
||||
|
@ -1897,7 +1887,7 @@ void DataBackup::on_backup_end(bool result)
|
|||
/**
|
||||
* @brief 最后备份结果界面
|
||||
*/
|
||||
void DataBackup::initLastWidget()
|
||||
void DataBackup::initLastPage()
|
||||
{
|
||||
QWidget *last = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
|
|
@ -37,13 +37,13 @@ public:
|
|||
~DataBackup();
|
||||
|
||||
private:
|
||||
void initFirstWidget();
|
||||
void initSecondWidget();
|
||||
void initSecondWidget_inc();
|
||||
void initThirdWidget();
|
||||
void initForthWidget();
|
||||
void initFifthWidget();
|
||||
void initLastWidget();
|
||||
void initHomePage();
|
||||
void initSetBackupPathsPage();
|
||||
void initSetIncPathsPage();
|
||||
void initCheckPage();
|
||||
void initNameBackupPage();
|
||||
void initBackupingPage();
|
||||
void initLastPage();
|
||||
|
||||
QList<ParseBackupList::BackupPoint> getBackupPointList();
|
||||
bool isExistsBackupName(const QString & backupName);
|
||||
|
|
|
@ -39,10 +39,10 @@ DataRestore::DataRestore(QWidget *parent) :
|
|||
m_pInterface = nullptr;
|
||||
|
||||
// 界面手写代码创建,作为练手
|
||||
initFirstWidget();
|
||||
initSecondWidget();
|
||||
initThirdWidget();
|
||||
initLastWidget();
|
||||
initHomePage();
|
||||
initCheckPage();
|
||||
initRestoringPage();
|
||||
initLastPage();
|
||||
}
|
||||
|
||||
DataRestore::~DataRestore()
|
||||
|
@ -54,7 +54,7 @@ DataRestore::~DataRestore()
|
|||
/**
|
||||
* @brief 初始化第一个页面
|
||||
*/
|
||||
void DataRestore::initFirstWidget()
|
||||
void DataRestore::initHomePage()
|
||||
{
|
||||
QWidget *homePage = new QWidget;
|
||||
QVBoxLayout *vLayout = new QVBoxLayout;
|
||||
|
@ -241,7 +241,7 @@ bool DataRestore::checkIsNeedReboot()
|
|||
/**
|
||||
* @brief 初始化第二界面--检测中
|
||||
*/
|
||||
void DataRestore::initSecondWidget()
|
||||
void DataRestore::initCheckPage()
|
||||
{
|
||||
QWidget *checkPage = new QWidget;
|
||||
|
||||
|
@ -611,7 +611,7 @@ void DataRestore::on_checkEnv_end(int result)
|
|||
/**
|
||||
* @brief 第三个页面-还原中
|
||||
*/
|
||||
void DataRestore::initThirdWidget()
|
||||
void DataRestore::initRestoringPage()
|
||||
{
|
||||
QWidget *restoringPage = new QWidget;
|
||||
|
||||
|
@ -847,7 +847,7 @@ void DataRestore::on_restore_end(bool result)
|
|||
/**
|
||||
* @brief 初始化最后一页
|
||||
*/
|
||||
void DataRestore::initLastWidget()
|
||||
void DataRestore::initLastPage()
|
||||
{
|
||||
QWidget *last = new QWidget;
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ public:
|
|||
virtual ~DataRestore();
|
||||
|
||||
private:
|
||||
void initFirstWidget();
|
||||
void initSecondWidget();
|
||||
void initThirdWidget();
|
||||
void initLastWidget();
|
||||
void initHomePage();
|
||||
void initCheckPage();
|
||||
void initRestoringPage();
|
||||
void initLastPage();
|
||||
|
||||
bool checkIsNeedReboot();
|
||||
|
||||
|
|
|
@ -44,11 +44,11 @@ GhostImage::GhostImage(QWidget *parent) :
|
|||
m_iPosition = BackupPosition::LOCAL;
|
||||
|
||||
// 界面手写代码创建,作为练手
|
||||
initFirstWidget();
|
||||
initSecondWidget();
|
||||
initThirdWidget();
|
||||
initForthWidget();
|
||||
initLastWidget();
|
||||
initHomePage();
|
||||
initSetSavePathPage();
|
||||
initCheckPage();
|
||||
initGhostingPage();
|
||||
initLastPage();
|
||||
}
|
||||
|
||||
GhostImage::~GhostImage()
|
||||
|
@ -63,7 +63,7 @@ GhostImage::~GhostImage()
|
|||
/**
|
||||
* @brief 初始化第一个页面
|
||||
*/
|
||||
void GhostImage::initFirstWidget()
|
||||
void GhostImage::initHomePage()
|
||||
{
|
||||
QWidget *homePage = new QWidget;
|
||||
QVBoxLayout *vLayout = new QVBoxLayout;
|
||||
|
@ -215,9 +215,9 @@ void GhostImage::on_next_clicked(bool checked)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第二个页面
|
||||
* @brief 初始化选择镜像保存位置页面
|
||||
*/
|
||||
void GhostImage::initSecondWidget()
|
||||
void GhostImage::initSetSavePathPage()
|
||||
{
|
||||
QWidget *savePathPage = new QWidget;
|
||||
// 纵向布局
|
||||
|
@ -311,9 +311,9 @@ void GhostImage::initSecondWidget()
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第三个页面
|
||||
* @brief 初始化检测页面
|
||||
*/
|
||||
void GhostImage::initThirdWidget()
|
||||
void GhostImage::initCheckPage()
|
||||
{
|
||||
QWidget *checkPage = new QWidget;
|
||||
|
||||
|
@ -742,9 +742,9 @@ QString GhostImage::createGhostImageName(const QString& backupName)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 第四个页面
|
||||
* @brief 初始化镜像创建页面
|
||||
*/
|
||||
void GhostImage::initForthWidget()
|
||||
void GhostImage::initGhostingPage()
|
||||
{
|
||||
QWidget *ghostingPage = new QWidget;
|
||||
|
||||
|
@ -1064,7 +1064,7 @@ void GhostImage::on_ghost_end(bool result)
|
|||
/**
|
||||
* @brief 最后备份结果界面
|
||||
*/
|
||||
void GhostImage::initLastWidget()
|
||||
void GhostImage::initLastPage()
|
||||
{
|
||||
QWidget *last = new QWidget;
|
||||
|
||||
|
|
|
@ -35,11 +35,11 @@ public:
|
|||
virtual ~GhostImage();
|
||||
|
||||
private:
|
||||
void initFirstWidget();
|
||||
void initSecondWidget();
|
||||
void initThirdWidget();
|
||||
void initForthWidget();
|
||||
void initLastWidget();
|
||||
void initHomePage();
|
||||
void initSetSavePathPage();
|
||||
void initCheckPage();
|
||||
void initGhostingPage();
|
||||
void initLastPage();
|
||||
QString createGhostImageName(const QString& backupName);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -150,6 +150,7 @@ void ManageBackupPointList::insertLines(const QList<ParseBackupList::BackupPoint
|
|||
} else {
|
||||
prefixPath_to_device = QObject::tr("Local Disk:") + " " + BACKUP_SNAPSHOTS_PATH;
|
||||
}
|
||||
prefixPath_to_device.replace("//", "/");
|
||||
setItem(indexOfRow, Column_Index::Backup_Device, prefixPath_to_device);
|
||||
if (backupPoint.m_state == BACKUP_PARSE_STATE_SUCCESS_STRTING) {
|
||||
setItem(indexOfRow, Column_Index::Backup_State, tr("backup finished"));
|
||||
|
|
|
@ -15,7 +15,7 @@ OperationLog::OperationLog(QWidget *parent) :
|
|||
QStackedWidget(parent)
|
||||
{
|
||||
// 界面手写代码创建,作为练手
|
||||
initFirstWidget();
|
||||
initHomePage();
|
||||
}
|
||||
|
||||
OperationLog::~OperationLog()
|
||||
|
@ -24,7 +24,7 @@ OperationLog::~OperationLog()
|
|||
/**
|
||||
* @brief 第一页
|
||||
*/
|
||||
void OperationLog::initFirstWidget()
|
||||
void OperationLog::initHomePage()
|
||||
{
|
||||
QWidget *homePage = new QWidget;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
virtual ~OperationLog();
|
||||
|
||||
private:
|
||||
void initFirstWidget();
|
||||
void initHomePage();
|
||||
void initOperationLogs(const QList<BackupWrapper>& list);
|
||||
void setItem(int row, int column, const QString& text, int alignFlag = Qt::AlignLeft | Qt::AlignVCenter);
|
||||
QString castTypeToString(int type);
|
||||
|
|
|
@ -173,6 +173,7 @@ void SelectRestorePoint::insertLines(const QList<ParseBackupList::BackupPoint> &
|
|||
} else {
|
||||
prefixPath_to_device = QObject::tr("Local Disk:") + " " + BACKUP_SNAPSHOTS_PATH;
|
||||
}
|
||||
prefixPath_to_device.replace("//", "/");
|
||||
setItem(indexOfRow, Column_Index::Backup_Device, prefixPath_to_device);
|
||||
setItem(indexOfRow, Column_Index::Backup_State, backupPoint.m_state);
|
||||
setItem(indexOfRow, Column_Index::Prefix_Path, backupPoint.m_path);
|
||||
|
|
|
@ -45,12 +45,12 @@ SystemBackup::SystemBackup(QWidget *parent /*= nullptr*/) :
|
|||
m_pInterface(nullptr)
|
||||
{
|
||||
// 界面手写代码创建,作为练手
|
||||
initFirstWidget();
|
||||
initSecondWidget();
|
||||
initThirdWidget();
|
||||
initForthWidget();
|
||||
initFifthWidget();
|
||||
initLastWidget();
|
||||
initHomePage();
|
||||
initSetBackupPathsPage();
|
||||
initCheckPage();
|
||||
initNameBackupPage();
|
||||
initBackupingPage();
|
||||
initLastPage();
|
||||
}
|
||||
|
||||
SystemBackup::~SystemBackup()
|
||||
|
@ -65,7 +65,7 @@ SystemBackup::~SystemBackup()
|
|||
/**
|
||||
* @brief 初始化第一个页面
|
||||
*/
|
||||
void SystemBackup::initFirstWidget()
|
||||
void SystemBackup::initHomePage()
|
||||
{
|
||||
QWidget *homePage = new QWidget;
|
||||
QVBoxLayout *vLayout = new QVBoxLayout;
|
||||
|
@ -167,6 +167,7 @@ void SystemBackup::initFirstWidget()
|
|||
backupPointManage->setProperty("useButtonPalette", true);
|
||||
QPalette pal(backupPointManage->palette());
|
||||
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Text, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Button, this->palette().base().color());
|
||||
backupPointManage->setPalette(pal);
|
||||
bottomHBoxLayout->addWidget(backupPointManage);
|
||||
|
@ -185,15 +186,19 @@ void SystemBackup::initFirstWidget()
|
|||
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::styleNameChanged, this, [=](bool isDark) {
|
||||
Q_UNUSED(isDark)
|
||||
// 深浅主题切换时,因为调色板已经更换,高亮等颜色已经改变,所以要重新加载图标。
|
||||
// from席博文:因为按钮的文字颜色换了一个类型,因为设计非要什么半透明透明效果的;Text就是半透明的,buttontext就是不半透明。所以将ButtonText改为Text
|
||||
QPalette pal(backupPointManage->palette());
|
||||
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Text, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Button, this->palette().base().color());
|
||||
backupPointManage->setPalette(pal);
|
||||
});
|
||||
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::themeColorChanged, this, [=]() {
|
||||
// 强调色更换,高亮等颜色已经改变,所以要重新加载图标。
|
||||
// from席博文:因为按钮的文字颜色换了一个类型,因为设计非要什么半透明透明效果的;Text就是半透明的,buttontext就是不半透明。所以将ButtonText改为Text
|
||||
QPalette pal(backupPointManage->palette());
|
||||
pal.setColor(QPalette::ButtonText, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Text, this->palette().highlight().color());
|
||||
pal.setColor(QPalette::Button, this->palette().base().color());
|
||||
backupPointManage->setPalette(pal);
|
||||
});
|
||||
|
@ -228,9 +233,9 @@ void SystemBackup::on_next_clicked(bool checked)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第二个页面
|
||||
* @brief 初始化选择备份文件页面
|
||||
*/
|
||||
void SystemBackup::initSecondWidget()
|
||||
void SystemBackup::initSetBackupPathsPage()
|
||||
{
|
||||
QWidget *selectPathPage = new QWidget;
|
||||
// 纵向布局
|
||||
|
@ -354,25 +359,7 @@ void SystemBackup::initSecondWidget()
|
|||
if (!selectFiles.isEmpty()) {
|
||||
QString fileName = selectFiles.at(0);
|
||||
|
||||
// sdk重新实现了QFileDialog后很多功能已经丢失,需要再次进行过滤,真难用
|
||||
QString backupPath = Utils::getSysRootPath() + BACKUP_PATH;
|
||||
backupPath.replace("//", "/");
|
||||
if (fileName == backupPath || fileName.contains(BACKUP_SNAPSHOTS_PATH)) {
|
||||
// 不能嵌套备份,请选择其它目录
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
|
||||
QObject::tr("Cannot nest backups, please select another directory."),
|
||||
QObject::tr("OK"));
|
||||
return ;
|
||||
} else if (fileName.endsWith(BACKUP_PATH)) {
|
||||
QString subfile = fileName + "/snapshots";
|
||||
if (Utils::isDirExist(subfile)) {
|
||||
// 不能嵌套备份,请选择其它目录
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
|
||||
QObject::tr("Cannot nest backups, please select another directory."),
|
||||
QObject::tr("OK"));
|
||||
return ;
|
||||
}
|
||||
} else if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
|
||||
if (Utils::isSubPath(this->m_udiskPaths, fileName)) {
|
||||
// 选择了移动设备挂载目录的子孙目录
|
||||
// 移动设备只能选择挂载目录本身
|
||||
MessageBoxUtils::QMESSAGE_BOX_WARNING(GlobelBackupInfo::instance().getMainWidget(), QObject::tr("Information"),
|
||||
|
@ -423,9 +410,9 @@ void SystemBackup::initSecondWidget()
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第三个页面
|
||||
* @brief 初始化检测中页面
|
||||
*/
|
||||
void SystemBackup::initThirdWidget()
|
||||
void SystemBackup::initCheckPage()
|
||||
{
|
||||
QWidget *checkPage = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
@ -748,8 +735,12 @@ void SystemBackup::on_checkEnv_start()
|
|||
backupWrapper.m_backupPaths << backupPath;
|
||||
backupWrapper.m_prefixDestPath = m_prefixDestPath;
|
||||
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
|
||||
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
|
||||
backupWrapper.m_backupExcludePaths << m_prefixDestPath;
|
||||
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE){
|
||||
QString prefixPath = m_prefixDestPath;
|
||||
prefixPath += BACKUP_SNAPSHOTS_PATH;
|
||||
prefixPath.replace("//", "/");
|
||||
backupWrapper.m_backupExcludePaths << prefixPath;
|
||||
}
|
||||
backupWrapper.m_frontUid = getuid();
|
||||
backupWrapper.m_frontUserName = qgetenv("USER");
|
||||
backupWrapper.m_gid = getgid();
|
||||
|
@ -822,10 +813,10 @@ void SystemBackup::on_checkEnv_end(int result)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化第四个页面
|
||||
* @brief 初始化备份命名页面
|
||||
*/
|
||||
#define MAX_LEN_BACKUPNAME 64
|
||||
void SystemBackup::initForthWidget()
|
||||
void SystemBackup::initNameBackupPage()
|
||||
{
|
||||
QWidget *nameBackupPage = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
@ -1098,9 +1089,9 @@ bool SystemBackup::isExistsBackupName(const QString & backupName)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief 第五个页面
|
||||
* @brief 初始化备份中页面
|
||||
*/
|
||||
void SystemBackup::initFifthWidget()
|
||||
void SystemBackup::initBackupingPage()
|
||||
{
|
||||
QWidget *backupingPage = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
@ -1293,8 +1284,12 @@ void SystemBackup::on_backup_start()
|
|||
backupWrapper.m_backupPaths << backupPath;
|
||||
backupWrapper.m_prefixDestPath = m_prefixDestPath;
|
||||
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
|
||||
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE)
|
||||
backupWrapper.m_backupExcludePaths << m_prefixDestPath;
|
||||
if (backupWrapper.m_iPosition == BackupPosition::CUSTOMIZE){
|
||||
QString prefixPath = m_prefixDestPath;
|
||||
prefixPath += BACKUP_SNAPSHOTS_PATH;
|
||||
prefixPath.replace("//", "/");
|
||||
backupWrapper.m_backupExcludePaths << prefixPath;
|
||||
}
|
||||
backupWrapper.m_frontUid = getuid();
|
||||
backupWrapper.m_frontUserName = qgetenv("USER");
|
||||
backupWrapper.m_gid = getgid();
|
||||
|
@ -1433,7 +1428,7 @@ void SystemBackup::on_backup_end(bool result)
|
|||
/**
|
||||
* @brief 最后备份结果界面
|
||||
*/
|
||||
void SystemBackup::initLastWidget()
|
||||
void SystemBackup::initLastPage()
|
||||
{
|
||||
QWidget *last = new QWidget;
|
||||
QVBoxLayout *vlayout = new QVBoxLayout;
|
||||
|
|
|
@ -35,12 +35,12 @@ public:
|
|||
~SystemBackup();
|
||||
|
||||
private:
|
||||
void initFirstWidget();
|
||||
void initSecondWidget();
|
||||
void initThirdWidget();
|
||||
void initForthWidget();
|
||||
void initFifthWidget();
|
||||
void initLastWidget();
|
||||
void initHomePage();
|
||||
void initSetBackupPathsPage();
|
||||
void initCheckPage();
|
||||
void initNameBackupPage();
|
||||
void initBackupingPage();
|
||||
void initLastPage();
|
||||
|
||||
QList<ParseBackupList::BackupPoint> getBackupPointList();
|
||||
bool isExistsBackupName(const QString & backupName);
|
||||
|
|
|
@ -42,10 +42,10 @@ SystemRestore::SystemRestore(QWidget *parent) :
|
|||
m_iPosition = BackupPosition::LOCAL;
|
||||
|
||||
// 界面手写代码创建,作为练手
|
||||
initFirstWidget();
|
||||
initSecondWidget();
|
||||
initThirdWidget();
|
||||
initLastWidget();
|
||||
initHomePage();
|
||||
initCheckPage();
|
||||
initRestoringPage();
|
||||
initLastPage();
|
||||
}
|
||||
|
||||
SystemRestore::~SystemRestore()
|
||||
|
@ -57,7 +57,7 @@ SystemRestore::~SystemRestore()
|
|||
/**
|
||||
* @brief 初始化第一个页面
|
||||
*/
|
||||
void SystemRestore::initFirstWidget()
|
||||
void SystemRestore::initHomePage()
|
||||
{
|
||||
QWidget *homePage = new QWidget;
|
||||
QVBoxLayout *vLayout = new QVBoxLayout;
|
||||
|
@ -259,7 +259,7 @@ void SystemRestore::on_button_beginRestore_clicked(bool checked)
|
|||
/**
|
||||
* @brief 初始化第二界面--检测中
|
||||
*/
|
||||
void SystemRestore::initSecondWidget()
|
||||
void SystemRestore::initCheckPage()
|
||||
{
|
||||
QWidget *checkPage = new QWidget;
|
||||
|
||||
|
@ -637,7 +637,7 @@ void SystemRestore::on_checkEnv_end(int result)
|
|||
/**
|
||||
* @brief 第三个页面-还原中
|
||||
*/
|
||||
void SystemRestore::initThirdWidget()
|
||||
void SystemRestore::initRestoringPage()
|
||||
{
|
||||
QWidget *restoringPage = new QWidget;
|
||||
|
||||
|
@ -874,7 +874,7 @@ void SystemRestore::on_restore_end(bool result)
|
|||
/**
|
||||
* @brief 初始化最后一页
|
||||
*/
|
||||
void SystemRestore::initLastWidget()
|
||||
void SystemRestore::initLastPage()
|
||||
{
|
||||
QWidget *last = new QWidget;
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ public:
|
|||
virtual ~SystemRestore();
|
||||
|
||||
private:
|
||||
void initFirstWidget();
|
||||
void initSecondWidget();
|
||||
void initThirdWidget();
|
||||
void initLastWidget();
|
||||
void initHomePage();
|
||||
void initCheckPage();
|
||||
void initRestoringPage();
|
||||
void initLastPage();
|
||||
|
||||
signals:
|
||||
void startCheckEnv();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
<クdハ<>箆!ソ`。スン
|
|
@ -1,13 +1,16 @@
|
|||
[Desktop Entry]
|
||||
Name=Backup and Restore
|
||||
Name=Backup & Restore
|
||||
Name[zh_CN]=备份还原
|
||||
Name[zh_HK]=備份還原
|
||||
Name[bo_CN]=རྗེས་གྲབས་དང་སླར་གསོ་བྱེད་དགོས།
|
||||
Name[mn]=ᠨᠥᠭᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠬᠦ
|
||||
Comment=Provides system and data backup and restore functions
|
||||
Comment[zh_CN]=提供系统备份还原和数据备份还原等功能
|
||||
Comment[bo_CN]=རྒྱུད་ཁོངས་གྲབས་ཉར་དང་གཞི་གྲངས་གྲབས་ཉར་སོར་ལོག་མཁོ་འདོན་སོགས་ཀྱི་ནུས་པ་
|
||||
Comment[mn]= ᠰᠢᠰᠲ᠋ᠧᠮ ᠤ᠋ᠨ ᠨᠦᠬᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠬᠦ᠂ ᠳ᠋ᠠᠢᠲ᠋ᠠ ᠵᠢᠨ ᠨᠥᠭᠡᠴᠡ ᠵᠢ ᠡᠬᠡᠬᠦᠯᠬᠦ ᠵᠡᠷᠭᠡ ᠴᠢᠳᠠᠪᠬᠢ ᠬᠠᠩᠭᠠᠠ
|
||||
Keywords=backup
|
||||
TryExec=kybackup
|
||||
Exec=/usr/bin/kybackup %U
|
||||
Exec=kybackup %U
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
|
Loading…
Reference in New Issue