urbackup_backend/urbackupclient/client_restore.cpp
2012-08-15 21:20:02 +02:00

1085 lines
25 KiB
C++

#include <string>
#include "../Interface/Server.h"
#include "../Interface/ThreadPool.h"
#include "../Interface/Thread.h"
#include "../Interface/File.h"
#include "../urbackupcommon/fileclient/tcpstack.h"
#include "../common/data.h"
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#include <algorithm>
#include "../urbackupserver/fileclient/socket_header.h"
#ifndef _WIN32
#include <net/if.h>
#include <sys/ioctl.h>
#endif
#include "../urbackupcommon/mbrdata.h"
#ifdef _WIN32
const std::string pw_file="pw.txt";
#else
const std::string pw_file="urbackup/pw.txt";
#endif
std::string trim2(const std::string &str)
{
size_t startpos=str.find_first_not_of(" \t\n");
size_t endpos=str.find_last_not_of(" \t\n");
if( std::string::npos == startpos || std::string::npos==endpos)
{
return "";
}
else
{
return str.substr( startpos, endpos-startpos+1);
}
}
std::string getResponse(IPipe *c)
{
CTCPStack tcpstack;
char *resp=NULL;
char buffer[1024];
size_t packetsize;
while(resp==NULL)
{
size_t rc=c->Read(buffer, 1024, 60000);
if(rc==0)
{
return "";
}
tcpstack.AddData(buffer, rc );
resp=tcpstack.getPacket(&packetsize);
if(resp!=NULL && packetsize==0)
{
delete []resp;
return "";
}
}
std::string ret;
ret.resize(packetsize);
memcpy(&ret[0], resp, packetsize);
delete []resp;
return ret;
}
std::vector<std::string> getBackupclients(int *ec)
{
std::string pw=getFile(pw_file);
CTCPStack tcpstack;
std::vector<std::string> ret;
*ec=0;
IPipe *c=Server->ConnectStream("localhost", 35623, 60000);
if(c==NULL)
{
Server->Log("Error connecting to client service -1", LL_ERROR);
*ec=10;
return ret;
}
tcpstack.Send(c, "GET BACKUPCLIENTS#pw="+pw);
std::string r=getResponse(c);
if(r.empty() )
{
Server->Log("No response from ClientConnector", LL_ERROR);
*ec=1;
}
else
{
if(r[0]=='0')
{
Server->Log("No backupserver found", LL_ERROR);
*ec=2;
}
else
{
std::vector<std::string> toks;
std::string t=r.substr(1);
Tokenize(t, toks, "\n");
for(size_t i=0;i<toks.size();++i)
{
std::string nam=trim2(getafter("|", toks[i]));
if(!nam.empty())
{
bool found=false;
for(size_t i=0;i<ret.size();++i)
{
if(ret[i]==nam)
{
found=true;
break;
}
}
if(!found)
{
ret.push_back(nam);
}
}
}
}
}
Server->destroy(c);
return ret;
}
struct SImage
{
bool operator<(const SImage &other) const
{
return other.time_s<time_s;
}
std::string time_str;
_i64 time_s;
int id;
std::vector<SImage> assoc;
std::string letter;
};
std::vector<SImage> getBackupimages(std::string clientname, int *ec)
{
std::string pw=getFile(pw_file);
CTCPStack tcpstack;
std::vector<SImage> ret;
*ec=0;
IPipe *c=Server->ConnectStream("localhost", 35623, 60000);
if(c==NULL)
{
Server->Log("Error connecting to client service -1", LL_ERROR);
*ec=10;
return ret;
}
tcpstack.Send(c, "GET BACKUPIMAGES "+clientname+"#pw="+pw);
std::string r=getResponse(c);
if(r.empty() )
{
Server->Log("No response from ClientConnector", LL_ERROR);
*ec=1;
}
else
{
if(r[0]=='0')
{
Server->Log("No backupserver found", LL_ERROR);
*ec=1;
}
else
{
std::vector<std::string> toks;
std::string t=r.substr(1);
Tokenize(t, toks, "\n");
for(size_t i=0;i<toks.size();++i)
{
std::vector<std::string> t2;
Tokenize(toks[i], t2, "|");
if(t2.size()==3 || (t2.size()==4 && t2[0]!="#") )
{
SImage si;
si.id=atoi(t2[0].c_str());
si.time_s=os_atoi64(t2[1]);
si.time_str=t2[2];
if(t2.size()==4)
{
si.letter=t2[3];
}
ret.push_back(si);
}
else if(t2.size()==4 && t2[0]=="#" && !ret.empty())
{
SImage si;
si.id=atoi(t2[1].c_str());
si.time_s=os_atoi64(t2[2]);
si.time_str=t2[3];
ret[ret.size()-1].assoc.push_back(si);
}
}
}
}
Server->destroy(c);
return ret;
}
volatile bool restore_retry_ok=false;
int downloadImage(int img_id, std::string img_time, std::string outfile, bool mbr, _i64 offset=-1)
{
std::string pw=getFile(pw_file);
CTCPStack tcpstack;
std::vector<SImage> ret;
IPipe *c=Server->ConnectStream("localhost", 35623, 60000);
if(c==NULL)
{
Server->Log("Error connecting to client service -1", LL_ERROR);
return 10;
}
std::string s_offset;
if(offset!=-1)
{
s_offset="&offset="+nconvert(offset);
}
tcpstack.Send(c, "DOWNLOAD IMAGE#pw="+pw+"&img_id="+nconvert(img_id)+"&time="+img_time+"&mbr="+nconvert(mbr)+s_offset);
std::string restore_out=outfile;
IFile *out=Server->openFile(restore_out, MODE_RW);
if(out==NULL)
{
Server->Log("Could not open \""+restore_out+"\" for writing", LL_ERROR);
Server->destroy(c);return 2;
}
_i64 imgsize=-1;
c->Read((char*)&imgsize, sizeof(_i64), 60000);
if(imgsize==-1)
{
Server->Log("Error reading size", LL_ERROR);
Server->destroy(c);Server->destroy(out);return 3;
}
char buf[4096];
if(mbr==true)
{
_i64 read=0;
while(read<imgsize)
{
size_t c_read=c->Read(buf, 4096, 180000);
if(c_read==0)
{
Server->Log("Read Timeout", LL_ERROR);
Server->destroy(c);Server->destroy(out);return 4;
}
out->Write(buf, (_u32)c_read);
read+=c_read;
}
Server->destroy(c);Server->destroy(out);return 0;
}
else
{
_i64 read=0;
/*while(read<512)
{
size_t c_read=c->Read(buf, 512-(size_t)read, 60000);
if(c_read==0)
{
Server->Log("Read Timeout -1", LL_ERROR);
Server->destroy(c);Server->destroy(out);return 4;
}
_u32 w=out->Write(buf,(_u32)c_read);
if(w!=c_read)
{
Server->Log("Writing to output file failed", LL_ERROR);
Server->destroy(c);Server->destroy(out);return 6;
}
read+=c_read;
}*/
unsigned int blockleft=0;
unsigned int off=0;
char blockdata[4096];
bool first=true;
bool has_data=false;
_i64 pos=0;
while(pos<imgsize)
{
size_t r=c->Read(&buf[off], 4096-off, 180000);
if(r!=0)
r+=off;
off=0;
if( r==0 )
{
Server->Log("Read Timeout: Retrying", LL_WARNING);
Server->destroy(c);Server->destroy(out);
if(has_data)
{
int tries=5;
int rc;
do
{
Server->wait(30000);
rc=downloadImage(img_id, img_time, outfile, mbr, pos);
if(rc==0)
{
return rc;
}
--tries;
}
while(tries>0);
return rc;
}
else
{
Server->Log("Read Timeout: No data", LL_ERROR);
return 4;
}
}
while(true)
{
if( blockleft==0 )
{
if(!first)
{
_u32 tw=4096;
if(imgsize>=pos && imgsize-pos<4096)
tw=(_u32)(imgsize-pos);
_u32 woff=0;
do
{
_u32 w=out->Write(&blockdata[woff], tw-woff);
if(w==0)
{
Server->Log("Writing to output file failed", LL_ERROR);
Server->destroy(c);Server->destroy(out);return 6;
}
woff+=w;
}
while(tw-woff>0);
has_data=true;
}
else
{
first=false;
if(pos!=-1 && !restore_retry_ok)
{
restore_retry_ok=true;
}
}
if(r-off>=sizeof(_i64) )
{
blockleft=4096;
_i64 s;
memcpy((char*)&s, &buf[off], sizeof(_i64) );
if(s>imgsize)
{
Server->Log("invalid seek value: "+nconvert(s), LL_ERROR);
pos=s;
break;
}
else if(s<pos)
{
Server->Log("Position out of order!", LL_ERROR);
}
else
{
out->Seek(s);
pos=s;
}
off+=sizeof(_i64);
}
else if(r-off>0)
{
char buf2[4096];
memcpy(buf2, &buf[off], r-off);
memcpy(buf, buf2, r-off);
off=(_u32)r-off;
break;
}
else
{
off=0;
break;
}
}
else
{
unsigned int available=(std::min)((unsigned int)r-off, blockleft);
if(available>0)
{
memcpy(&blockdata[4096-blockleft], &buf[off], (_u32)available );
}
read+=available;
blockleft-=available;
off+=available;
if(off>=r)
{
off=0;
break;
}
}
}
}
Server->destroy(c);Server->destroy(out);return 0;
}
return 0;
}
void do_restore(void)
{
IPipe *c=Server->ConnectStream("localhost", 35623, 60000);
if(c==NULL)
{
Server->Log("Error connecting to client service -1", LL_ERROR);
exit(1);return;
}
std::string pw=getFile(pw_file);
CTCPStack tcpstack;
std::string cmd=Server->getServerParameter("restore_cmd");
if(cmd=="get_clientnames")
{
tcpstack.Send(c, "GET BACKUPCLIENTS#pw="+pw);
std::string r=getResponse(c);
if(r.empty() )
{
Server->Log("No response from ClientConnector", LL_ERROR);
Server->destroy(c);exit(2);return;
}
else
{
if(r[0]=='0')
{
Server->Log("No backupserver found", LL_ERROR);
Server->destroy(c);exit(3);return;
}
else
{
std::cout << r.substr(1) ;
Server->destroy(c);exit(0);return;
}
}
}
else if(cmd=="get_backupimages" )
{
tcpstack.Send(c, "GET BACKUPIMAGES "+Server->getServerParameter("restore_name")+"#pw="+pw);
std::string r=getResponse(c);
if(r.empty() )
{
Server->Log("No response from ClientConnector", LL_ERROR);
Server->destroy(c);exit(2);return;
}
else
{
if(r[0]=='0')
{
Server->Log("No backupserver found", LL_ERROR);
Server->destroy(c);exit(3);return;
}
else
{
std::cout << r.substr(1) ;
Server->destroy(c);exit(0);return;
}
}
}
else if(cmd=="download_mbr" || cmd=="download_image" )
{
bool mbr=false;
if(cmd=="download_mbr")
mbr=true;
int ec=downloadImage(atoi(Server->getServerParameter("restore_img_id").c_str()), Server->getServerParameter("restore_time"), Server->getServerParameter("restore_out"), mbr);
exit(ec);
}
else if(cmd=="download_progress")
{
tcpstack.Send(c, "GET DOWNLOADPROGRESS#pw="+pw);
int lpc=0;
while(true)
{
std::string curr;
size_t r=c->Read(&curr, 10000);
for(int i=0;i<linecount(curr);++i)
{
std::string l=getline(i, curr);
if(!trim2(l).empty())
{
int npc=atoi(trim2(l).c_str());
if(npc!=lpc)
{
std::cout << npc << std::endl;
lpc=npc;
}
}
}
if(r==0)
break;
}
if(lpc!=100)
{
std::cout << "100" << std::endl;
}
exit(0);
}
}
class RestoreThread : public IThread
{
public:
RestoreThread(int pImg_id, std::string pImg_time, std::string pOutfile) : img_id(pImg_id), img_time(pImg_time), outfile(pOutfile)
{
done=false;
}
void operator()(void)
{
rc=downloadImage(img_id, img_time, outfile, false);
done=true;
}
bool isDone(void)
{
return done;
}
int getRC(void)
{
return rc;
}
private:
int rc;
volatile bool done;
int img_id;
std::string img_time;
std::string outfile;
};
bool has_network_device(void)
{
#ifdef _WIN32
return true;
#else
#ifdef sun
return true;
#else
char buf[1024];
struct ifconf ifc;
struct ifreq *ifr;
int sck;
int nInterfaces;
int i;
/* Get a socket handle. */
sck = socket(AF_INET, SOCK_DGRAM, 0);
if(sck < 0)
{
return true;
}
/* Query available interfaces. */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if(ioctl(sck, SIOCGIFCONF, &ifc) < 0)
{
close(sck);
return true;
}
/* Iterate through the list of interfaces. */
ifr = ifc.ifc_req;
nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
for(i = 0; i < nInterfaces; i++)
{
struct ifreq *item = &ifr[i];
if(htonl(INADDR_LOOPBACK)!=((struct sockaddr_in *)&item->ifr_addr)->sin_addr.s_addr )
{
close(sck);
return true;
}
}
close(sck);
return false;
#endif //sun
#endif //_WIN32
}
const int start_state=-2;
void restore_wizard(void)
{
int state=start_state;
std::vector<std::string> clients;
std::string clientname;
std::vector<SImage> images;
SImage selimage;
SImage r_selimage;
std::string seldrive;
int selpart;
std::string err;
bool res_sysvol=false;
while(true)
{
switch(state)
{
case -2:
{
system("dialog --msgbox \"`cat urbackup/restore/welcome`\" 10 70");
++state;
}break;
case -1:
{
if(!has_network_device())
{
system("clear");
system("cat urbackup/restore/search_network");
int tries=20;
bool has_interface=false;
do
{
bool b=has_network_device();
if(b)
{
has_interface=true;
break;
}
--tries;
Server->wait(1000);
} while(tries>=0);
if(has_interface==false)
{
int r=system("dialog --menu \"`cat urbackup/restore/no_network_device`\" 15 50 10 \"n\" \"`cat urbackup/restore/configure_networkcard`\" \"w\" \"`cat urbackup/restore/configure_wlan`\" \"e\" \"`cat urbackup/restore/start_shell`\" \"c\" \"`cat urbackup/restore/continue_restore`\" 2> out");
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
if(out=="n")
{
system("LC_ALL=C netcardconfig");
state=0;
}
else if(out=="w")
{
system("LC_ALL=C wlcardconfig");
state=0;
}
else if(out=="e")
{
system("bash");
state=0;
}
else if(out=="c")
state=0;
else
state=99;
}
else
{
state=0;
}
}
else
{
state=0;
}
}break;
case 0:
{
system("urbackup/restore/progress-start.sh | dialog --backtitle \"`cat urbackup/restore/search`\" --gauge \"`cat urbackup/restore/t_progress`\" 6 60 0");
++state;
}break;
case 1:
{
int ec;
clients=getBackupclients(&ec);
std::string errmsg;
switch(ec)
{
case 10:
case 1:
errmsg="`cat urbackup/restore/internal_error`";
break;
case 2:
errmsg="`cat urbackup/restore/no_server_found`";
break;
}
if(clients.empty())
{
ec=3;
errmsg="`cat urbackup/restore/no_clients_found`";
}
if(ec!=0)
{
int r=system(("dialog --menu \"`cat urbackup/restore/error_happend` "+errmsg+". `cat urbackup/restore/how_to_continue`\" 15 50 10 \"r\" \"`cat urbackup/restore/search_again`\" \"n\" \"`cat urbackup/restore/configure_networkcard`\" \"w\" \"`cat urbackup/restore/configure_wlan`\" \"e\" \"`cat urbackup/restore/start_shell`\" \"s\" \"`cat urbackup/restore/stop_restore`\" 2> out").c_str());
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
if(out=="r")
state=0;
else if(out=="n")
{
system("LC_ALL=C netcardconfig");
state=0;
}
else if(out=="w")
{
system("LC_ALL=C wlcardconfig");
state=0;
}
else if(out=="e")
{
system("bash");
state=0;
}
else
state=99;
}
else
{
std::string mi;
for(size_t i=0;i<clients.size();++i)
{
mi+="\""+nconvert((int)i+1)+"\" \""+clients[i]+"\" ";
}
int r=system(("dialog --menu \"`cat urbackup/restore/select`\" 15 50 10 "+mi+"2> out").c_str());
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
clientname=clients[atoi(out.c_str())-1];
++state;
}
}break;
case 2:
{
int ec;
images=getBackupimages(clientname, &ec);
std::string errmsg;
switch(ec)
{
case 10:
case 1:
errmsg="`cat urbackup/restore/internal_error`";
break;
case 2:
errmsg="`cat urbackup/restore/no_server_found`";
break;
}
if(images.empty())
{
ec=3;
errmsg="`cat urbackup/restore/no_images_for_client1` '"+clientname+"' `cat urbackup/restore/no_images_for_client2`";
}
std::sort(images.begin(), images.end());
if(ec!=0)
{
int r=system(("dialog --menu \"`cat urbackup/restore/error_happend` "+errmsg+". `cat urbackup/restore/how_to_continue`\" 15 50 10 \"a\" \"`cat urbackup/restore/error_j_select`\" \"r\" \"`cat urbackup/restore/search_again`\" \"s\" \"`cat urbackup/restore/stop_restore`\" 2> out").c_str());
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
if(out=="r")
state=0;
else if(out=="a")
state=1;
else
state=99;
}
else
{
std::string mi;
for(size_t i=0;i<images.size();++i)
{
if(!images[i].letter.empty())
images[i].letter=" "+images[i].letter;
mi+="\""+nconvert((int)i+1)+"\" \""+images[i].time_str+images[i].letter+"\" ";
}
int r=system(("dialog --menu \"`cat urbackup/restore/select_date`\" 15 50 10 "+mi+"2> out").c_str());
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
selimage=images[atoi(out.c_str())-1];
r_selimage=selimage;
++state;
}
}break;
case 3:
{
system("ls /dev | grep \"[h|s]d[a-z]\" > out");
std::string drives_s=getFile("out");
std::vector<std::string> drives;
for(int i=0,lc=linecount(drives_s);i<lc;++i)
{
std::string l=trim2(getline(i, drives_s));
if(l.size()==3)
{
drives.push_back(l);
}
}
std::vector<std::string> vendors;
std::vector<_i64> d_sizes;
for(size_t i=0;i<drives.size();++i)
{
system(("hdparm -I /dev/"+drives[i]+" | grep Model > out").c_str());
std::string out=getFile("out");
std::string vendor=trim2(getafter("Model Number:", out));
if(vendor.empty())
{
vendor="`cat urbackup/restore/unknown_disk`";
}
vendors.push_back(vendor);
system(("hdparm -I /dev/"+drives[i]+" | grep \"M = 1000\" > out").c_str());
out=getFile("out");
std::string size_s=trim2(getbetween("1000:", "MBytes", out));
d_sizes.push_back(os_atoi64(size_s));
}
if(drives.empty())
{
int r=system("dialog --menu \"`cat urbackup/restore/no_disks_found`. `cat urbackup/restore/how_to_continue`\" 15 50 10 \"r\" \"`cat urbackup/restore/search_disk_again`\" \"s\" \"`cat urbackup/restore/stop_restore`\" 2> out");
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
if(out=="r")
state=3;
else
state=99;
break;
}
std::string mi;
for(size_t i=0;i<drives.size();++i)
{
mi+="\""+nconvert((int)i+1)+"\" \""+vendors[i]+" `cat urbackup/restore/size`: "+nconvert((int)(d_sizes[i]/1000))+" GB\" ";
}
std::string scmd="dialog --menu \"`cat urbackup/restore/select_drive`\" 15 50 10 "+mi+"2> out";
writestring(scmd, "scmd.sh");
int r=system(scmd.c_str());
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
int driveidx=atoi(out.c_str())-1;
seldrive=drives[driveidx];
r=system(("dialog --yesno \"`cat urbackup/restore/select_certain`\\n"+vendors[driveidx]+" `cat urbackup/restore/size`: "+nconvert((int)(d_sizes[driveidx]/1000))+" GB\" 10 50").c_str());
if(r!=0)
{
break;
}
++state;
}break;
case 4:
{
system("clear");
system("cat urbackup/restore/loading_mbr");
system("echo");
system("touch mbr.dat");
downloadImage(selimage.id, nconvert(selimage.time_s), "mbr.dat", true);
system("cat urbackup/restore/reading_mbr");
system("echo");
IFile *f=Server->openFile("mbr.dat", MODE_READ);
if(f==NULL)
{
err="cannot_read_mbr";
state=101;
break;
}
size_t fsize=(size_t)f->Size();
char *buf=new char[fsize];
f->Read(buf, (_u32)fsize);
Server->destroy(f);
CRData mbr(buf, fsize);
SMBRData mbrdata(mbr);
if(mbrdata.hasError())
{
err="error_while_reading_mbr";
exit(3);
state=101;
break;
}
system("cat urbackup/restore/writing_mbr");
system("echo");
IFile *dev=Server->openFile("/dev/"+seldrive, MODE_RW);
if(dev==NULL)
{
err="cannot_open_disk";
state=101;
break;
}
dev->Seek(0);
dev->Write(mbrdata.mbr_data);
Server->destroy(dev);
system("cat urbackup/restore/reading_partition_table");
system("echo");
system(("partprobe /dev/"+seldrive+" > /dev/null 2>&1").c_str());
Server->wait(10000);
system("cat urbackup/restore/testing_partition");
system("echo");
dev=Server->openFile("/dev/"+seldrive+nconvert(mbrdata.partition_number), MODE_RW);
int try_c=0;
while(dev==NULL && try_c<10)
{
system(("partprobe /dev/"+seldrive+" > /dev/null 2>&1").c_str());
Server->wait(10000);
system("cat urbackup/restore/testing_partition");
system("echo");
dev=Server->openFile("/dev/"+seldrive+nconvert(mbrdata.partition_number), MODE_RW);
++try_c;
}
if(dev==NULL)
{
err="no_restore_partition";
state=101;
break;
}
selpart=mbrdata.partition_number;
Server->destroy(dev);
delete []buf;
++state;
}break;
case 5:
{
RestoreThread rt(selimage.id, nconvert(selimage.time_s), "/dev/"+seldrive+nconvert( selpart ));
THREADPOOL_TICKET rt_ticket=Server->getThreadPool()->execute(&rt);
while(true)
{
system(("./cserver --plugin urbackup/.libs/liburbackup.so --no-server --restore true --restore_cmd download_progress | dialog --backtitle \"`cat urbackup/restore/restoration"+(std::string)(res_sysvol?"_sysvol":"")+"`\" --gauge \"`cat urbackup/restore/t_progress`\" 6 60 0").c_str());
while(!rt.isDone() && !restore_retry_ok)
{
Server->wait(1000);
}
if(rt.isDone())
break;
if(restore_retry_ok)
restore_retry_ok=false;
}
Server->getThreadPool()->waitFor(rt_ticket);
int rc=rt.getRC();
std::string errmsg;
switch(rc)
{
case 10: errmsg="`cat urbackup/restore/no_connection`"; break;
case 2: errmsg="`cat urbackup/restore/cannot_write_on_partition`"; break;
case 3: errmsg="`cat urbackup/restore/wrong_size`"; break;
case 4: errmsg="`cat urbackup/restore/server_doesnot_respond`"; break;
case 6: errmsg="`cat urbackup/restore/writing_failed`"; break;
};
if(rc!=0)
{
int r=system(("dialog --menu \"`cat urbackup/restore/error_happend`: "+errmsg+". `cat urbackup/restore/how_to_continue`\" 15 50 10 \"r\" \"`cat urbackup/restore/restart_restore`\" \"e\" \"`cat urbackup/restore/error_happend`\" \"o\" \"`cat urbackup/restore/start_shell`\" \"s\" \"`cat urbackup/restore/stop_restore`\" 2> out").c_str());
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
if(out=="r")
state=5;
else if(out=="o")
state=3;
else if(out=="e")
{
system("bash");
state=0;
}
else
state=99;
}
else
{
if(r_selimage.assoc.size()>0)
{
selimage=r_selimage.assoc[0];
r_selimage.assoc.erase(r_selimage.assoc.begin());
res_sysvol=true;
state=4;
}
else
{
++state;
}
}
}break;
case 6:
{
int r=system("dialog --menu \"`cat urbackup/restore/restore_success`\" 15 50 10 \"r\" \"`cat urbackup/restore/restart_computer`\" \"o\" \"`cat urbackup/restore/restore_other`\" \"s\" \"`cat urbackup/restore/stop_restore`\" 2> out");
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
if(out=="r")
system("init 6");
else if(out=="o")
state=2;
else if(out=="s")
system("bash");
else
system("init 6");
}break;
case 99:
{
system("dialog --msgbox \"`cat urbackup/restore/computer_halt`\" 7 50");
system("init 0");
exit(1);
}break;
case 101:
{
int r=system(("dialog --menu \"`cat urbackup/restore/error_happend` `cat urbackup/restore/"+err+"`. `cat urbackup/restore/how_to_continue`\" 15 50 10 \"r\" \"`cat urbackup/restore/restart_restore`\" \"s\" \"`cat urbackup/restore/stop_restore`\" 2> out").c_str());
if(r!=0)
{
state=start_state;
break;
}
std::string out=getFile("out");
if(out=="r")
state=0;
else
state=99;
}break;
default:
{
system("dialog --msgbox \"`cat urbackup/restore/internal_error`!!!!\" 7 50");
exit(99);
}break;
}
}
}