mirror of
https://github.com/hamonikr/systemback.git
synced 2025-12-24 06:27:49 -05:00
665 lines
26 KiB
C++
665 lines
26 KiB
C++
/*
|
|
* Copyright(C) 2014-2016, Franco Conidi <edmondweblog@gmail.com>
|
|
*
|
|
* This file is part of the Systemback.
|
|
*
|
|
* The Systemback is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
* Foundation; either version 3 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* The Systemback is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with the
|
|
* Systemback. If not, see <http://www.gnu.org/licenses>.
|
|
*/
|
|
|
|
#include "systemback-cli.hpp"
|
|
#include <QTextStream>
|
|
#include <QDateTime>
|
|
#include <QDir>
|
|
#include <ncursesw/ncurses.h>
|
|
|
|
#ifdef timeout
|
|
#undef timeout
|
|
#endif
|
|
|
|
#ifdef instr
|
|
#undef instr
|
|
#endif
|
|
|
|
void systemback::main()
|
|
{
|
|
auto help([] {
|
|
return tr("Usage: systemback-cli [option]\n\n"
|
|
" Options:\n\n"
|
|
" -n, --newbackup create a new restore point\n\n"
|
|
" -s, --storagedir <path> get or set the restore points storage directory path\n\n"
|
|
" -u, --upgrade upgrade the current system\n"
|
|
" remove the unnecessary files and packages\n\n"
|
|
" -v, --version output the Systemback version number\n\n"
|
|
" -h, --help show this help");
|
|
});
|
|
|
|
uchar rv([&] {
|
|
QSL args(qApp->arguments());
|
|
|
|
if(args.count() == 1 || [&] {
|
|
if(sb::like(args.at(1), {"_-h_", "_--help_"}))
|
|
sb::print("\n " % help() % "\n\n");
|
|
else if(sb::like(args.at(1), {"_-v_", "_--version_"}))
|
|
sb::print("\n " % sb::appver() % "\n\n");
|
|
else
|
|
return true;
|
|
|
|
return false;
|
|
}()) return sb::isfile("/cdrom/casper/filesystem.squashfs") || sb::isfile("/lib/live/mount/medium/live/filesystem.squashfs") ? 2
|
|
: getuid() + getgid() ? 3
|
|
: ! sb::lock(sb::Sblock) ? 4
|
|
: ! sb::lock(sb::Dpkglock) ? 5
|
|
: ! sb::lock(sb::Aptlock) ? 6
|
|
: [&] {
|
|
auto startui([this](bool crtrpt = false) -> uchar {
|
|
if(! (isatty(fileno(stdin)) && isatty(fileno(stdout)) && isatty(fileno(stderr)))) return 255;
|
|
initscr();
|
|
|
|
uchar crv(! has_colors() ? 7
|
|
: LINES < 24 || COLS < 80 ? 8
|
|
: [crtrpt, this]() -> uchar {
|
|
noecho(),
|
|
raw(),
|
|
curs_set(0),
|
|
attron(A_BOLD),
|
|
start_color(),
|
|
assume_default_colors(COLOR_BLUE, COLOR_BLACK),
|
|
init_pair(1, COLOR_WHITE, COLOR_BLACK),
|
|
init_pair(2, COLOR_BLUE, COLOR_BLACK),
|
|
init_pair(3, COLOR_GREEN, COLOR_BLACK),
|
|
init_pair(4, COLOR_YELLOW, COLOR_BLACK),
|
|
init_pair(5, COLOR_RED, COLOR_BLACK),
|
|
sbtxt = bstr("Systemback " % tr("basic restore UI")), blgn = COLS / 2 - 6 - tr("basic restore UI").length() / 2;
|
|
if(! crtrpt) return clistart();
|
|
sb::pupgrade();
|
|
return newrpnt() ? 0 : sb::dfree(sb::sdir[1]) < 104857600 ? 12 : 13;
|
|
}());
|
|
|
|
endwin();
|
|
return crv;
|
|
});
|
|
|
|
return args.count() == 1 ? startui()
|
|
: sb::like(args.at(1), {"_-n_", "_--newrestorepoint_"}) ? sb::isdir(sb::sdir[1]) && sb::access(sb::sdir[1], sb::Write) ? startui(true) : 14
|
|
: sb::like(args.at(1), {"_-s_", "_--storagedir_"}) ? storagedir(args)
|
|
: sb::like(args.at(1), {"_-u_", "_--upgrade_"}) ? [] {
|
|
sb::unlock(sb::Dpkglock), sb::unlock(sb::Aptlock),
|
|
sb::supgrade();
|
|
return 0;
|
|
}() : 1;
|
|
}();
|
|
|
|
return 0;
|
|
}());
|
|
|
|
if(! sb::like(rv, {0, 255})) sb::error("\n " % [=]() -> QStr {
|
|
auto dbg([](cQStr &txt) {
|
|
if(! sb::eout.isEmpty()) sb::crtfile("/tmp/systemback-cli_stderr", QStr((sb::dbglev == sb::sb::Cextdbg ? sb::dbginf() : nullptr) % sb::eout).trimmed().replace("\n\n\n", "\n\n").replace("\n ", "\n") % '\n');
|
|
return txt;
|
|
});
|
|
|
|
switch(rv) {
|
|
case 1:
|
|
return help();
|
|
case 2:
|
|
return tr("The Systemback command line interface cannot be used on a Live system!");
|
|
case 3:
|
|
return tr("Root privileges are required for running the Systemback!");
|
|
case 4:
|
|
return tr("An another Systemback process is currently running, please wait until it finishes.");
|
|
case 5:
|
|
return tr("Unable to get exclusive lock!") % "\n\n " % tr("First, close all package manager.");
|
|
case 6:
|
|
return tr("The re-synchronization of package index files currently in progress, please wait until it finishes.");
|
|
case 7:
|
|
return tr("This stupid terminal does not support color!");
|
|
case 8:
|
|
return tr("This terminal is too small!") % " (< 80x24)";
|
|
case 9:
|
|
return tr("The specified storage directory path has not been set!");
|
|
case 10:
|
|
return tr("The restoration is aborted!");
|
|
case 11:
|
|
return dbg(tr("The restoration is completed, but an error occurred while reinstalling the GRUB!"));
|
|
case 12:
|
|
return dbg(tr("The restore point creation is aborted!") % "\n\n " % tr("Not enough free disk space to complete the process."));
|
|
case 13:
|
|
return dbg(tr("The restore point creation is aborted!") % "\n\n " % tr("There has been critical changes in the file system during this operation."));
|
|
case 14:
|
|
return dbg(tr("The restore points storage directory is not available or not writable!"));
|
|
default:
|
|
return dbg(tr("The restore point deletion is aborted!") % "\n\n " % tr("An error occurred while during the process."));
|
|
}
|
|
}() % "\n\n");
|
|
|
|
qApp->exit(rv);
|
|
}
|
|
|
|
uchar systemback::clistart()
|
|
{
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(bstr("\n\n " % tr("Available restore point(s):") % "\n\n")),
|
|
sb::pupgrade(),
|
|
attron(COLOR_PAIR(3));
|
|
if(! sb::pnames[0].isEmpty()) printw(bstr(" 1 ─ " % sb::left(sb::pnames[0], COLS - 7) % '\n'));
|
|
if(! sb::pnames[1].isEmpty()) printw(bstr(" 2 ─ " % sb::left(sb::pnames[1], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 3) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[2].isEmpty()) printw(bstr(" 3 ─ " % sb::left(sb::pnames[2], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 4) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[3].isEmpty()) printw(bstr(" 4 ─ " % sb::left(sb::pnames[3], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 5) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[4].isEmpty()) printw(bstr(" 5 ─ " % sb::left(sb::pnames[4], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 6) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[5].isEmpty()) printw(bstr(" 6 ─ " % sb::left(sb::pnames[5], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 7) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[6].isEmpty()) printw(bstr(" 7 ─ " % sb::left(sb::pnames[6], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 8) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[7].isEmpty()) printw(bstr(" 8 ─ " % sb::left(sb::pnames[7], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 9) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[8].isEmpty()) printw(bstr(" 9 ─ " % sb::left(sb::pnames[8], COLS - 7) % '\n'));
|
|
if(sb::pnumber == 10) attron(COLOR_PAIR(5));
|
|
if(! sb::pnames[9].isEmpty()) printw(bstr(" A ─ " % sb::left(sb::pnames[9], COLS - 7) % '\n'));
|
|
attron(COLOR_PAIR(3));
|
|
if(! sb::pnames[10].isEmpty()) printw(bstr(" B ─ " % sb::left(sb::pnames[10], COLS - 7) % '\n'));
|
|
if(! sb::pnames[11].isEmpty()) printw(bstr(" C ─ " % sb::left(sb::pnames[11], COLS - 7) % '\n'));
|
|
if(! sb::pnames[12].isEmpty()) printw(bstr(" D ─ " % sb::left(sb::pnames[12], COLS - 7) % '\n'));
|
|
if(! sb::pnames[13].isEmpty()) printw(bstr(" E ─ " % sb::left(sb::pnames[13], COLS - 7) % '\n'));
|
|
if(! sb::pnames[14].isEmpty()) printw(bstr(" F ─ " % sb::left(sb::pnames[14], COLS - 7) % '\n'));
|
|
printw(bstr("\n G ─ " % tr("Create new") % "\n Q ─ " % tr("Quit") % '\n')),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
if(! sb::eout.isEmpty()) sb::eout.clear();
|
|
if(! pname.isEmpty()) pname.clear();
|
|
|
|
do {
|
|
int gtch(getch());
|
|
|
|
switch(gtch) {
|
|
case '1' ... '9':
|
|
{
|
|
QStr cstr(gtch);
|
|
cpoint = "S0" % cstr;
|
|
uchar num(cstr.toUShort() - 1);
|
|
if(! sb::pnames[num].isEmpty()) pname = sb::pnames[num];
|
|
break;
|
|
}
|
|
case 'a':
|
|
case 'A':
|
|
cpoint = "S10";
|
|
if(! sb::pnames[9].isEmpty()) pname = sb::pnames[9];
|
|
break;
|
|
case 'b':
|
|
case 'B':
|
|
cpoint = "H01";
|
|
if(! sb::pnames[10].isEmpty()) pname = sb::pnames[10];
|
|
break;
|
|
case 'c':
|
|
case 'C':
|
|
cpoint = "H02";
|
|
if(! sb::pnames[11].isEmpty()) pname = sb::pnames[11];
|
|
break;
|
|
case 'd':
|
|
case 'D':
|
|
cpoint = "H03";
|
|
if(! sb::pnames[12].isEmpty()) pname = sb::pnames[12];
|
|
break;
|
|
case 'e':
|
|
case 'E':
|
|
cpoint = "H04";
|
|
if(! sb::pnames[13].isEmpty()) pname = sb::pnames[13];
|
|
break;
|
|
case 'f':
|
|
case 'F':
|
|
cpoint = "H05";
|
|
if(! sb::pnames[14].isEmpty()) pname = sb::pnames[14];
|
|
break;
|
|
case 'g':
|
|
case 'G':
|
|
if(! newrpnt()) return sb::dfree(sb::sdir[1]) < 104857600 ? 12 : 13;
|
|
clear();
|
|
return clistart();
|
|
case 'q':
|
|
case 'Q':
|
|
return 0;
|
|
}
|
|
} while(pname.isEmpty());
|
|
|
|
clear(),
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(bstr("\n\n " % tr("Selected restore point:"))),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(bstr("\n\n " % sb::left(pname, COLS - 3))),
|
|
attron(COLOR_PAIR(3)),
|
|
printw(bstr("\n\n 1 ─ " % tr("Delete") % "\n 2 ─ " % tr("System restore") % " ▸\n B ─ ◂ " % tr("Back"))),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
|
|
forever
|
|
switch(getch()) {
|
|
case '1':
|
|
pset(2), progress(Start);
|
|
|
|
if(! (sb::rename(sb::sdir[1] % '/' % cpoint % '_' % pname, sb::sdir[1] % "/.DELETED_" % pname) && sb::remove(sb::sdir[1] % "/.DELETED_" % pname)))
|
|
{
|
|
progress(Stop);
|
|
return 15;
|
|
}
|
|
|
|
emptycache(),
|
|
progress(Stop),
|
|
clear();
|
|
return clistart();
|
|
case '2':
|
|
clear();
|
|
return restore();
|
|
case 'b':
|
|
case 'B':
|
|
clear();
|
|
return clistart();
|
|
}
|
|
}
|
|
|
|
uchar systemback::storagedir(cQSL &args)
|
|
{
|
|
if(args.count() == 2)
|
|
sb::print("\n " % sb::sdir[0] % "\n\n");
|
|
else
|
|
{
|
|
QStr ndir;
|
|
|
|
{
|
|
QStr cpath, idir(args.at(2));
|
|
|
|
if(args.count() > 3)
|
|
for(uchar a(3) ; a < args.count() ; ++a) idir.append(' ' % args.at(a));
|
|
|
|
QSL excl{"*/Systemback_", "*/Systemback/*", "*/_", "_/bin_", "_/bin/*", "_/boot_", "_/boot/*", "_/cdrom_", "_/cdrom/*", "_/dev_", "_/dev/*", "_/etc_", "_/etc/*", "_/lib_", "_/lib/*", "_/lib32_", "_/lib32/*", "_/lib64_", "_/lib64/*", "_/opt_", "_/opt/*", "_/proc_", "_/proc/*", "_/root_", "_/root/*", "_/run_", "_/run/*", "_/sbin_", "_/sbin/*", "_/selinux_", "_/selinux/*", "_/snap_", "_/snap/*", "_/srv_", "_/srv/*_", "_/sys_", "_/sys/*", "_/tmp_", "_/tmp/*", "_/usr_", "_/usr/*", "_/var_", "_/var/*"};
|
|
if(sb::like(ndir = QDir::cleanPath(idir), excl) || sb::like(cpath = QDir(idir).canonicalPath(), excl) || sb::like(sb::fload("/etc/passwd"), {"*:" % idir % ":*","*:" % ndir % ":*", "*:" % cpath % ":*"}) || ! sb::islnxfs(cpath)) return 9;
|
|
}
|
|
|
|
if(sb::sdir[0] != ndir)
|
|
{
|
|
if(sb::isdir(sb::sdir[1]))
|
|
{
|
|
QSL dlst(QDir(sb::sdir[1]).entryList(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot));
|
|
|
|
if(! dlst.count())
|
|
rmdir(bstr(sb::sdir[1]));
|
|
else if(dlst.count() == 1 && sb::isfile(sb::sdir[1] % "/.sbschedule"))
|
|
sb::remove(sb::sdir[1]);
|
|
}
|
|
|
|
sb::sdir[0] = ndir, sb::sdir[1] = sb::sdir[0] % "/Systemback", sb::ismpnt = ! sb::issmfs(sb::sdir[0], sb::sdir[0].count('/') == 1 ? "/" : sb::left(sb::sdir[0], sb::rinstr(sb::sdir[0], "/") - 1));
|
|
if(! sb::cfgwrite()) return 9;
|
|
}
|
|
|
|
if(! (sb::isdir(sb::sdir[1]) || sb::crtdir(sb::sdir[1]))) sb::rename(sb::sdir[1], sb::sdir[1] % '_' % sb::rndstr()),
|
|
sb::crtdir(sb::sdir[1]);
|
|
|
|
if(! sb::isfile(sb::sdir[1] % "/.sbschedule")) sb::crtfile(sb::sdir[1] % "/.sbschedule");
|
|
sb::print("\n " % twrp(tr("The specified storage directory path is set.")) % "\n\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void systemback::emptycache()
|
|
{
|
|
pset(1),
|
|
sb::fssync();
|
|
if(sb::ecache) sb::crtfile("/proc/sys/vm/drop_caches", "3");
|
|
}
|
|
|
|
bool systemback::newrpnt()
|
|
{
|
|
auto end([this](bool rv = true) {
|
|
progress(Stop);
|
|
return rv;
|
|
});
|
|
|
|
progress(Start);
|
|
|
|
for(cQStr &item : QDir(sb::sdir[1]).entryList(QDir::Dirs | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot))
|
|
if(sb::like(item, {"_.DELETED_*", "_.S00_*"}))
|
|
{
|
|
if(prun.type != 3) pset(3);
|
|
if(! sb::remove(sb::sdir[1] % '/' % item)) return end(false);
|
|
}
|
|
|
|
for(uchar a(9) ; a > 1 ; --a)
|
|
if(! sb::pnames[a].isEmpty() && (a == 9 || a > 2 ? sb::pnumber < a + 2 : sb::pnumber == 3))
|
|
{
|
|
if(prun.type != 4) pset(4);
|
|
if(! (sb::rename(sb::sdir[1] % (a < 9 ? QStr("/S0" % QStr::number(a + 1)) : "/S10") % '_' % sb::pnames[a], sb::sdir[1] % "/.DELETED_" % sb::pnames[a]) && sb::remove(sb::sdir[1] % "/.DELETED_" % sb::pnames[a]))) return end(false);
|
|
}
|
|
|
|
pset(5);
|
|
QStr dtime(QDateTime().currentDateTime().toString("yyyy-MM-dd,hh.mm.ss"));
|
|
if(! sb::crtrpoint(dtime)) return end(false);
|
|
|
|
for(uchar a(0) ; a < 9 && sb::isdir(sb::sdir[1] % "/S0" % QStr::number(a + 1) % '_' % sb::pnames[a]) ; ++a)
|
|
if(! sb::rename(sb::sdir[1] % "/S0" % QStr::number(a + 1) % '_' % sb::pnames[a], sb::sdir[1] % (a < 8 ? "/S0" : "/S") % QStr::number(a + 2) % '_' % sb::pnames[a])) return end(false);
|
|
|
|
if(! sb::rename(sb::sdir[1] % "/.S00_" % dtime, sb::sdir[1] % "/S01_" % dtime)) return end(false);
|
|
sb::crtfile(sb::sdir[1] % "/.sbschedule"),
|
|
emptycache();
|
|
return end();
|
|
}
|
|
|
|
uchar systemback::restore()
|
|
{
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1));
|
|
uchar mthd(0), fsave(0), greinst(0);
|
|
|
|
{
|
|
bstr rtxt[3]{bstr("\n\n " % tr("Restore with the following restore point:")), bstr("\n\n " % pname), bstr("\n\n " % tr("Restore with the following restore method:"))};
|
|
printw(rtxt[0]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(rtxt[1]),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[2]),
|
|
attron(COLOR_PAIR(3)),
|
|
printw(bstr("\n\n 1 ─ " % tr("Full restore") % "\n 2 ─ " % tr("System files restore"))),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(bstr("\n\n " % tr("Users configuration files restore"))),
|
|
attron(COLOR_PAIR(3)),
|
|
printw(bstr("\n\n 3 ─ " % tr("Complete configuration files restore") % "\n 4 ─ " % tr("Keep newly installed configuration files") % "\n\n C ─ " % tr("Cancel"))),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
|
|
do {
|
|
int gtch(getch());
|
|
|
|
switch(gtch) {
|
|
case 'c':
|
|
case 'C':
|
|
clear();
|
|
return clistart();
|
|
case '1' ... '4':
|
|
mthd = QStr(gtch).toUShort();
|
|
}
|
|
} while(! mthd);
|
|
|
|
clear(),
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[0]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(rtxt[1]),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[2]),
|
|
attron(COLOR_PAIR(4));
|
|
|
|
printw(bstr("\n\n " % [mthd] {
|
|
switch(mthd) {
|
|
case 1:
|
|
return tr("Full restore");
|
|
case 2:
|
|
return tr("System files restore");
|
|
case 3:
|
|
return tr("Complete configuration files restore");
|
|
default:
|
|
return tr("Configuration files restore");
|
|
}
|
|
}()));
|
|
|
|
attron(COLOR_PAIR(3));
|
|
|
|
if(mthd < 3)
|
|
{
|
|
if(sb::isfile("/etc/fstab"))
|
|
{
|
|
printw(bstr("\n\n " % tr("You want to keep the current fstab file?") % ' ' % tr("(Y/N)"))),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
|
|
do {
|
|
QChar gtch(getch());
|
|
|
|
if(sb::like(gtch.toUpper(), {"_Y_", '_' % yn[0] % '_'}))
|
|
fsave = 1;
|
|
else if(sb::like(gtch.toUpper(), {"_N_", '_' % yn[1] % '_'}))
|
|
fsave = 2;
|
|
} while(! fsave);
|
|
|
|
clear(),
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[0]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(rtxt[1]),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[2]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(bstr("\n\n " % (mthd == 1 ? tr("Full restore") : tr("System files restore")) % "\n\n " % tr("You want to keep the current fstab file?") % ' ' % tr("(Y/N)") % ' ' % yn[fsave == 1 ? 0 : 1])),
|
|
attron(COLOR_PAIR(3));
|
|
|
|
if(sb::execsrch("update-grub2", sb::sdir[1] % '/' % cpoint % '_' % pname))
|
|
{
|
|
printw(bstr("\n\n " % tr("Reinstall the GRUB 2 bootloader?") % ' ' % tr("(Y/N)"))),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
|
|
do {
|
|
QChar gtch(getch());
|
|
|
|
if(sb::like(gtch.toUpper(), {"_Y_", '_' % yn[0] % '_'}))
|
|
greinst = 1;
|
|
else if(sb::like(gtch.toUpper(), {"_N_", '_' % yn[1] % '_'}))
|
|
greinst = 2;
|
|
} while(! greinst);
|
|
|
|
clear(),
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[0]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(rtxt[1]),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[2]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(bstr("\n\n " % (mthd == 1 ? tr("Full restore") : tr("System files restore")) % "\n\n " % tr("You want to keep the current fstab file?") % ' ' % tr("(Y/N)") % ' ' % yn[fsave == 1 ? 0 : 1] % "\n\n " % tr("Reinstall the GRUB 2 bootloader?") % ' ' % tr("(Y/N)") % ' ' % yn[greinst == 1 ? 0 : 1]));
|
|
}
|
|
}
|
|
else if(sb::execsrch("update-grub2", sb::sdir[1] % '/' % cpoint % '_' % pname))
|
|
{
|
|
printw(bstr("\n\n " % tr("Reinstall the GRUB 2 bootloader?") % ' ' % tr("(Y/N)"))),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
|
|
do {
|
|
QChar gtch(getch());
|
|
|
|
if(sb::like(gtch.toUpper(), {"_Y_", '_' % yn[0] % '_'}))
|
|
greinst = 1;
|
|
else if(sb::like(gtch.toUpper(), {"_N_", '_' % yn[1] % '_'}))
|
|
greinst = 2;
|
|
} while(! greinst);
|
|
|
|
clear(),
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[0]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(rtxt[1]),
|
|
attron(COLOR_PAIR(1)),
|
|
printw(rtxt[2]),
|
|
attron(COLOR_PAIR(4)),
|
|
printw(bstr("\n\n " % (mthd == 1 ? tr("Full restore") : tr("System files restore")) % "\n\n " % tr("Reinstall the GRUB 2 bootloader?") % ' ' % tr("(Y/N)") % ' ' % yn[greinst == 1 ? 0 : 1]));
|
|
}
|
|
}
|
|
}
|
|
|
|
attron(COLOR_PAIR(3)),
|
|
printw(bstr("\n\n " % tr("Start the restore?") % ' ' % tr("(Y/N)"))),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
bool rstart(false);
|
|
|
|
do {
|
|
QChar gtch(getch());
|
|
|
|
if(sb::like(gtch.toUpper(), {"_Y_", '_' % yn[0] % '_'}))
|
|
rstart = true;
|
|
else if(sb::like(gtch.toUpper(), {"_N_", '_' % yn[1] % '_'}))
|
|
return 10;
|
|
} while(! rstart);
|
|
|
|
pset(mthd + 5),
|
|
progress(Start);
|
|
bool sfstab(fsave == 1);
|
|
sb::srestore(mthd, nullptr, sb::sdir[1] % '/' % cpoint % '_' % pname, nullptr, sfstab);
|
|
{ bool err(greinst == 1 && sb::exec("sh -c \"update-grub ; grub-install --force " % sb::gdetect() % '\"', sb::Silent));
|
|
progress(Stop);
|
|
if(err) return 11; }
|
|
clear(),
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1));
|
|
|
|
printw(bstr("\n\n " % twrp([mthd] {
|
|
switch(mthd) {
|
|
case 1:
|
|
return tr("The full system restoration is completed.");
|
|
case 2:
|
|
return tr("The system files restoration are completed.");
|
|
case 3:
|
|
return tr("The users configuration files full restoration are completed.");
|
|
default:
|
|
return tr("The users configuration files restoration are completed.");
|
|
}
|
|
}())));
|
|
|
|
attron(COLOR_PAIR(3)),
|
|
printw(bstr("\n\n " % twrp(mthd < 3 ? tr("Press 'ENTER' key to reboot the computer, or 'Q' to quit.") : tr("Press 'ENTER' key to quit.")))),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
|
|
forever
|
|
switch(getch()) {
|
|
case '\n':
|
|
if(mthd < 3) sb::exec(sb::execsrch("reboot") ? "reboot" : "systemctl reboot", sb::Bckgrnd);
|
|
return 0;
|
|
case 'q':
|
|
case 'Q':
|
|
if(mthd < 3) return 0;
|
|
}
|
|
}
|
|
|
|
void systemback::pset(uchar type)
|
|
{
|
|
prun.txt = [type]() -> QStr {
|
|
switch(type) {
|
|
case 1:
|
|
return sb::ecache ? tr("Emptying cache") : tr("Flushing filesystem buffers");
|
|
case 2:
|
|
return tr("Deleting restore point");
|
|
case 3:
|
|
return tr("Deleting incomplete restore point");
|
|
case 4:
|
|
return tr("Deleting old restore point(s)");
|
|
case 5:
|
|
return tr("Creating restore point");
|
|
case 6:
|
|
return tr("Restoring the full system");
|
|
case 7:
|
|
return tr("Restoring the system files");
|
|
default:
|
|
return tr("Restoring the users configuration files");
|
|
}
|
|
}();
|
|
|
|
prun.type = type;
|
|
}
|
|
|
|
void systemback::progress(uchar status)
|
|
{
|
|
switch(status) {
|
|
case Start:
|
|
connect(ptimer = new QTimer, SIGNAL(timeout()), this, SLOT(progress())),
|
|
QTimer::singleShot(0, this, SLOT(progress())),
|
|
ptimer->start(2000);
|
|
if(sb::dbglev == sb::Nulldbg) sb::dbglev = sb::Errdbg;
|
|
return;
|
|
case Inprog:
|
|
for(uchar a(0) ; a < 4 ; ++a)
|
|
{
|
|
switch(prun.type) {
|
|
case 5 ... 9:
|
|
{
|
|
schar cperc(sb::Progress);
|
|
|
|
if(cperc == -1)
|
|
prun.pbar = prun.pbar == " (?%)" ? " ( %)" : " (?%)";
|
|
else if(cperc > 99)
|
|
{
|
|
if(prun.cperc < 100) prun.cperc = 100, prun.pbar = " (100%)";
|
|
}
|
|
else if(prun.cperc < cperc)
|
|
prun.pbar = " (" % QStr::number(prun.cperc = cperc) % "%)";
|
|
else if(! (prun.cperc || prun.pbar == " (0%)"))
|
|
prun.pbar = " (0%)";
|
|
else if(sb::like(99, {cperc, prun.cperc}, true))
|
|
prun.pbar = " (100%)", prun.cperc = 100;
|
|
|
|
break;
|
|
}
|
|
default:
|
|
if(! prun.pbar.isEmpty()) prun.pbar.clear();
|
|
}
|
|
|
|
if(! ptimer) return;
|
|
clear(),
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(0, blgn, sbtxt),
|
|
attron(COLOR_PAIR(1));
|
|
|
|
mvprintw(LINES / 2 - 1, COLS / 2 - (prun.txt.length() + prun.pbar.length() + 4) / 2, bstr(prun.txt % prun.pbar % [a] {
|
|
switch(a) {
|
|
case 0:
|
|
return " ";
|
|
case 1:
|
|
return " . ";
|
|
case 2:
|
|
return " .. ";
|
|
default:
|
|
return " ...";
|
|
}
|
|
}()));
|
|
|
|
attron(COLOR_PAIR(2)),
|
|
mvprintw(LINES - 1, COLS - 13, "HamoniKR"),
|
|
refresh();
|
|
if(a < 3) sb::delay(500);
|
|
}
|
|
|
|
break;
|
|
case Stop:
|
|
delete ptimer, ptimer = nullptr;
|
|
prun.txt.clear();
|
|
if(! prun.pbar.isEmpty()) prun.pbar.clear();
|
|
if(prun.cperc) prun.cperc = 0;
|
|
if(sb::Progress > -1) sb::Progress = -1;
|
|
}
|
|
}
|