/*************************************************************************
* UrBackup - Client/Server backup system
* Copyright (C) 2011-2016 Martin Raiber
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
**************************************************************************/
#include
#include
#include
#include "Connector.h"
#include "../stringtools.h"
#include "../tclap/CmdLine.h"
#ifndef _WIN32
#include "../config.h"
#define PWFILE VARDIR "/urbackup/pw.txt"
#else
#define PACKAGE_VERSION "$version_full_numeric$"
#define VARDIR ""
#define PWFILE "pw.txt"
#endif
const std::string cmdline_version = PACKAGE_VERSION;
void show_version()
{
std::cout << "UrBackup Client Controller v" << cmdline_version << std::endl;
std::cout << "Copyright (C) 2011-2016 Martin Raiber" << std::endl;
std::cout << "This is free software; see the source for copying conditions. There is NO"<< std::endl;
std::cout << "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."<< std::endl;
}
void action_help(std::string cmd)
{
std::cout << std::endl;
std::cout << "USAGE:" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " [--help] [--version] []" << std::endl;
std::cout << std::endl;
std::cout << "Get specific command help with " << cmd << " --help" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " start" << std::endl;
std::cout << "\t\t" "Start an incremental/full image/file backup" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " status" << std::endl;
std::cout << "\t\t" "Get current backup status" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " list" << std::endl;
std::cout << "\t\t" "List backups and files/folders in backups" << std::endl;
std::cout << std::endl;
}
typedef int(*action_fun)(std::vector args);
class PwClientCmd
{
public:
PwClientCmd(TCLAP::CmdLine& cmd)
: cmd(cmd),
pw_file_arg("p", "pw-file",
"Use password in file",
false, PWFILE, "path", cmd),
client_arg("c", "client",
"Start backup on this client",
false, "127.0.0.1", "hostname/IP", cmd)
{
}
void set()
{
Connector::setPWFile(pw_file_arg.getValue());
Connector::setClient(client_arg.getValue());
}
private:
TCLAP::CmdLine& cmd;
TCLAP::ValueArg pw_file_arg;
TCLAP::ValueArg client_arg;
};
int action_start(std::vector args)
{
TCLAP::CmdLine cmd("Start an incremental/full image/file backup", ' ', cmdline_version);
TCLAP::SwitchArg incr_backup("i", "incremental", "Start incremental backup");
TCLAP::SwitchArg full_backup("f", "full", "Start full backup");
cmd.xorAdd(incr_backup, full_backup);
TCLAP::SwitchArg file_backup("l", "file", "Start file backup");
TCLAP::SwitchArg image_backup("m", "image", "Start image backup");
cmd.xorAdd(file_backup, image_backup);
PwClientCmd pw_client_cmd(cmd);
cmd.parse(args);
pw_client_cmd.set();
int rc;
if(file_backup.getValue())
{
rc = Connector::startBackup(full_backup.getValue());
}
else
{
rc = Connector::startImage(full_backup.getValue());
}
if(rc==2)
{
std::cout << "Backup is already running" << std::endl;
return 2;
}
else if(rc==1)
{
std::cout << "Backup started" << std::endl;
return 0;
}
else if(rc==3)
{
std::cout << "Error starting backup. No backup server found." << std::endl;
return 3;
}
else
{
std::cerr << "Error starting backup." << std::endl;
return 1;
}
}
int action_status(std::vector args)
{
TCLAP::CmdLine cmd("Get current backup status", ' ', cmdline_version);
PwClientCmd pw_client_cmd(cmd);
cmd.parse(args);
pw_client_cmd.set();
std::string status = Connector::getStatusDetail();
if(!status.empty())
{
std::cout << status << std::endl;
return 0;
}
else
{
std::cerr << "Error getting status" << std::endl;
return 1;
}
}
int action_list(std::vector args)
{
TCLAP::CmdLine cmd("List backups and files/folders in backups", ' ', cmdline_version);
PwClientCmd pw_client_cmd(cmd);
TCLAP::ValueArg backupid_arg("b", "backupid",
"Backupid of backup from which to list files/folders",
false, 0, "id", cmd);
TCLAP::ValueArg path_arg("d", "path",
"Path of folder/file of which to list backups/contents",
false, "", "path", cmd);
cmd.parse(args);
pw_client_cmd.set();
if(path_arg.getValue().empty() && !backupid_arg.isSet())
{
bool no_server;
std::string filebackups = Connector::getFileBackupsList(no_server);
if(!filebackups.empty())
{
std::cout << filebackups << std::endl;
return 0;
}
else
{
if(no_server)
{
std::cerr << "Error getting file backups. No backup server found." << std::endl;
return 2;
}
else
{
std::cerr << "Error getting file backups" << std::endl;
return 1;
}
}
}
else
{
int* pbackupid = NULL;
if(backupid_arg.isSet())
{
pbackupid = &backupid_arg.getValue();
}
bool no_server;
std::string filelist = Connector::getFileList(path_arg.getValue(), pbackupid, no_server);
if(!filelist.empty())
{
std::cout << filelist << std::endl;
return 0;
}
else
{
if(no_server)
{
std::cerr << "Error getting file list. No backup server found." << std::endl;
return 2;
}
else
{
std::cerr << "Error getting file list" << std::endl;
return 1;
}
}
}
}
int action_start_restore(std::vector args)
{
TCLAP::CmdLine cmd("Restore files/folders from backup", ' ', cmdline_version);
PwClientCmd pw_client_cmd(cmd);
TCLAP::ValueArg backupid_arg("b", "backupid",
"Backupid of backup from which to restore files/folders",
true, 0, "id", cmd);
TCLAP::ValueArg path_arg("d", "path",
"Path of folder/file to restore",
false, "", "path", cmd);
TCLAP::MultiArg map_from_arg("m", "map-from",
"Map from local output path of folders/files to a different local path",
false, "path", cmd);
TCLAP::MultiArg map_to_arg("t", "map-to",
"Map to local output path of folders/files to a different local path",
false, "path", cmd);
cmd.parse(args);
if (map_from_arg.getValue().size() != map_to_arg.getValue().size())
{
std::cerr << "There need to be an equal amount of -m/--map-from and -t/--map-to arguments" << std::endl;
return 2;
}
pw_client_cmd.set();
std::vector path_map;
for (size_t i = 0; i < map_from_arg.getValue().size(); ++i)
{
SPathMap new_pm;
new_pm.source = map_from_arg.getValue()[i];
new_pm.target = map_to_arg.getValue()[i];
path_map.push_back(new_pm);
}
bool no_server;
std::string restore_info = Connector::startRestore(path_arg.getValue(), backupid_arg.getValue(), path_map, no_server);
if(!restore_info.empty())
{
std::cout << restore_info << std::endl;
return 0;
}
else
{
if(no_server)
{
std::cerr << "Error starting restore. No backup server found." << std::endl;
return 2;
}
else
{
std::cerr << "Error starting restore" << std::endl;
return 1;
}
}
}
int main(int argc, char *argv[])
{
if(argc==0)
{
std::cout << "Not enough arguments (zero arguments) -- no program name" << std::endl;
return 1;
}
std::vector actions;
std::vector action_funs;
actions.push_back("start");
action_funs.push_back(action_start);
actions.push_back("status");
action_funs.push_back(action_status);
actions.push_back("list");
action_funs.push_back(action_list);
actions.push_back("restore-start");
action_funs.push_back(action_start_restore);
bool has_help=false;
bool has_version=false;
size_t action_idx=std::string::npos;
std::vector args;
args.push_back(argv[0]);
for(int i=1;i