urbackup_backend/urbackupserver/cmdline_preprocessor.cpp
Martin 6447563c2e Merge remote-tracking branch 'urpc/next' into dev
Conflicts:
	.gitignore
	Interface/Database.h
	configure.ac_client
	configure.ac_server
	fileservplugin/CClientThread.cpp
	fileservplugin/CClientThread.h
	fileservplugin/FileServFactory.cpp
	fileservplugin/FileServFactory.h
	fileservplugin/IFileServFactory.h
	fsimageplugin/FSImageFactory.cpp
	fsimageplugin/FSImageFactory.h
	fsimageplugin/FileWrapper.cpp
	fsimageplugin/FileWrapper.h
	fsimageplugin/IFSImageFactory.h
	fsimageplugin/Makefile.am_client
	fsimageplugin/Makefile.am_server
	fsimageplugin/dllmain.cpp
	fsimageplugin/filesystem.cpp
	fsimageplugin/filesystem.h
	fsimageplugin/fs/ntfs.cpp
	fsimageplugin/fs/ntfs.h
	fsimageplugin/fs/ntfs_win.cpp
	fsimageplugin/fs/ntfs_win.h
	fsimageplugin/fs/unknown.cpp
	fsimageplugin/fs/unknown.h
	fsimageplugin/fsimageplugin.vcxproj.filters
	start_urbackup_client
	start_urbackup_server
	urbackupclient/ChangeJournalWatcher.cpp
	urbackupclient/ClientService.cpp
	urbackupclient/ClientServiceCMD.cpp
	urbackupclient/ImageThread.cpp
	urbackupclient/client.cpp
	urbackupclient/client.h
	urbackupclient/client_restore.cpp
	urbackupclient/clientdao.cpp
	urbackupclient/dllmain.cpp
	urbackupclient/win_sysvol.cpp
	urbackupclient/win_sysvol.h
	urbackupcommon/fileclient/FileClient.cpp
	urbackupcommon/fileclient/FileClientChunked.cpp
	urbackupcommon/os_functions.h
	urbackupcommon/os_functions_lin.cpp
	urbackupcommon/os_functions_win.cpp
	urbackupcommon/settingslist.cpp
	urbackupserver/ImageBackup.cpp
	urbackupserver/SQLiteFileCache.cpp
	urbackupserver/ServerDownloadThread.cpp
	urbackupserver/dao/ServerBackupDao.cpp
	urbackupserver/dao/ServerBackupDao.h
	urbackupserver/dllmain.cpp
	urbackupserver/doc/admin_guide.tex
	urbackupserver/server_channel.cpp
	urbackupserver/server_channel.h
	urbackupserver/server_cleanup.cpp
	urbackupserver/server_dir_links.cpp
	urbackupserver/server_get.cpp
	urbackupserver/server_hash.cpp
	urbackupserver/server_hash.h
	urbackupserver/server_settings.cpp
	urbackupserver/server_settings.h
	urbackupserver/server_update_stats.cpp
	urbackupserver/server_writer.cpp
	urbackupserver/serverinterface/backups.cpp
	urbackupserver/serverinterface/settings.cpp
	urbackupserver/serverinterface/usage.cpp
	urbackupserver/www/js/urbackup.js
	urbackupserver/www/templates.js
	urbackupserver/www/templates/settings_inv_row.htm
	urbackupserver/www/translations/urbackup.webinterface/ar_SA.po
2015-12-09 14:49:13 +01:00

901 lines
24 KiB
C++

#include "../tclap/CmdLine.h"
#include <vector>
#include "../stringtools.h"
#include "../urbackupcommon/os_functions.h"
#include <stdlib.h>
#ifndef _WIN32
# include "../Server.h"
# include <sys/types.h>
# include <pwd.h>
# include <sys/wait.h>
# include <ctime>
# include <sys/time.h>
# include <unistd.h>
# include <sys/types.h>
# include <pwd.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <sys/fcntl.h>
# include <memory>
# include "../Interface/SettingsReader.h"
#endif
#ifndef _WIN32
#include "config.h"
#define _getcwd getcwd
#else
#define PACKAGE_VERSION "unknown"
#define VARDIR ""
#include <direct.h>
#endif
const std::string cmdline_version = PACKAGE_VERSION;
void show_version()
{
std::cout << "UrBackup Server v" << cmdline_version << std::endl;
std::cout << "Copyright (C) 2011-2015 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;
}
int64 get_time_ms()
{
#ifndef _WIN32
timespec tp;
if(clock_gettime(CLOCK_MONOTONIC, &tp)!=0)
{
timeval tv;
gettimeofday(&tv, NULL);
static long start_t=tv.tv_sec;
tv.tv_sec-=start_t;
return tv.tv_sec*1000+tv.tv_usec/1000;
}
return static_cast<int64>(tp.tv_sec)*1000+tp.tv_nsec/1000000;
#else
return 0;
#endif
}
int real_main(int argc, char* argv[])
#ifndef _WIN32
;
#else
{return 1;}
#endif
int run_real_main(std::vector<std::string> args)
{
char** argv = new char*[args.size()];
for(size_t i=0;i<args.size();++i)
{
argv[i] = const_cast<char*>(args[i].c_str());
}
int rc = real_main(static_cast<int>(args.size()), argv);
delete[] argv;
return rc;
}
typedef int(*action_fun)(std::vector<std::string> args);
std::string unquote_value(std::string val)
{
val = trim(val);
if(val[0]=='"')
{
size_t last_pos = val.find_last_of('"');
if(last_pos!=0)
{
val=val.substr(1, last_pos-1);
}
}
else if(val[0]=='\'')
{
size_t last_pos = val.find_last_of('\'');
if(last_pos!=0)
{
val=val.substr(1, last_pos-1);
}
}
return val;
}
#ifndef _WIN32
void read_config_file(std::string fn, std::vector<std::string>& real_args)
{
bool destroy_server=false;
if(Server==NULL)
{
Server = new CServer;
destroy_server=true;
}
{
std::auto_ptr<ISettingsReader> settings(Server->createFileSettingsReader(fn));
std::string val;
if(settings->getValue("FASTCGI_PORT", &val))
{
val = unquote_value(val);
if(!val.empty())
{
real_args.push_back("--port");
real_args.push_back(val);
}
}
if(settings->getValue("HTTP_PORT", &val))
{
val = unquote_value(val);
if(!val.empty())
{
real_args.push_back("--http_port");
real_args.push_back(val);
}
}
if(settings->getValue("LOGFILE", &val))
{
val = unquote_value(val);
if(!val.empty())
{
if(val[0]!='/')
{
val = "/var/log/"+val;
}
real_args.push_back("--logfile");
real_args.push_back(val);
}
}
if(settings->getValue("LOGLEVEL", &val))
{
val = unquote_value(val);
if(!val.empty())
{
real_args.push_back("--loglevel");
real_args.push_back(unquote_value(val));
}
}
if(settings->getValue("DAEMON_TMPDIR", &val))
{
std::string tmpdir = unquote_value(val);
if(!tmpdir.empty())
{
if(setenv("TMPDIR", tmpdir.c_str(), 1)!=0)
{
std::cout << "Error setting TMPDIR" << std::endl;
exit(1);
}
}
}
if(settings->getValue("SQLITE_TMPDIR", &val))
{
val = unquote_value(val);
if(!val.empty())
{
real_args.push_back("--sqlite_tmpdir");
real_args.push_back(val);
}
}
if(settings->getValue("BROADCAST_INTERFACES", &val))
{
val = unquote_value(val);
if(!val.empty())
{
real_args.push_back("--broadcast_interfaces");
real_args.push_back(val);
}
}
}
if(destroy_server)
{
delete Server;
}
}
#endif
int action_run(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Run network file and image backup server", ' ', cmdline_version);
TCLAP::ValueArg<unsigned short> fastcgi_port_arg("f", "fastcgi-port",
"Specifies the port where UrBackup server will listen for FastCGI connections",
false, 55413, "port number", cmd);
TCLAP::ValueArg<unsigned short> http_port_arg("p", "http-port",
"Specifies the port where UrBackup server will listen for HTTP connections",
false, 55414, "port number", cmd);
TCLAP::ValueArg<std::string> logfile_arg("l", "logfile",
"Specifies the log file name",
false, "/var/log/urbackup.log", "path", cmd);
std::vector<std::string> loglevels;
loglevels.push_back("debug");
loglevels.push_back("info");
loglevels.push_back("warn");
loglevels.push_back("error");
TCLAP::ValuesConstraint<std::string> loglevels_constraint(loglevels);
TCLAP::ValueArg<std::string> loglevel_arg("v", "loglevel",
"Specifies the log level",
false, "info", &loglevels_constraint, cmd);
TCLAP::SwitchArg no_console_time_arg("t", "no-consoletime",
"Do not print time when logging to console",
cmd, false);
TCLAP::SwitchArg daemon_arg("d", "daemon", "Daemonize process", cmd, false);
TCLAP::ValueArg<std::string> pidfile_arg("w", "pidfile",
"Save pid of daemon in file",
false, "/var/run/urbackup_client.pid", "path", cmd);
TCLAP::MultiArg<std::string> broadcast_interface_arg("b", "broadcast-interface",
"Network interface from which to send broadcasts", false, "network interface name", cmd);
TCLAP::ValueArg<std::string> sqlite_tmpdir_arg("s", "sqlite-tmpdir",
"Specifies the directory SQLite uses to store temporary tables",
false, "", "path", cmd);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
#ifndef _WIN32
TCLAP::ValueArg<std::string> config_arg("c", "config",
"Read configuration parameters from config file",
false, "", "path", cmd);
#endif
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
#ifndef _WIN32
if(!config_arg.getValue().empty())
{
read_config_file(config_arg.getValue(), real_args);
}
#endif
if(std::find(real_args.begin(), real_args.end(), "--port")==real_args.end())
{
real_args.push_back("--port");
real_args.push_back(nconvert(fastcgi_port_arg.getValue()));
}
if(std::find(real_args.begin(), real_args.end(), "--http_port")==real_args.end())
{
real_args.push_back("--http_port");
real_args.push_back(nconvert(http_port_arg.getValue()));
}
real_args.push_back("--pidfile");
real_args.push_back(pidfile_arg.getValue());
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
if(!sqlite_tmpdir_arg.getValue().empty())
{
real_args.push_back("--sqlite_tmpdir");
real_args.push_back(sqlite_tmpdir_arg.getValue());
}
std::string broadcast_interfaces;
const std::vector<std::string>& bi = broadcast_interface_arg.getValue();
for(size_t i=0;i<bi.size();++i)
{
if(!broadcast_interfaces.empty())
{
broadcast_interfaces+=",";
}
broadcast_interfaces+=bi[i];
}
if(!broadcast_interfaces.empty()
&& std::find(real_args.begin(), real_args.end(), "--broadcast_interfaces")==real_args.end())
{
real_args.push_back("--broadcast_interfaces");
real_args.push_back(broadcast_interfaces);
}
if(std::find(real_args.begin(), real_args.end(), "--logfile")==real_args.end())
{
real_args.push_back("--logfile");
real_args.push_back(logfile_arg.getValue());
}
if(std::find(real_args.begin(), real_args.end(), "--loglevel")==real_args.end())
{
real_args.push_back("--loglevel");
real_args.push_back(loglevel_arg.getValue());
}
if(daemon_arg.getValue())
{
real_args.push_back("--daemon");
}
if(no_console_time_arg.getValue())
{
real_args.push_back("--log_console_no_time");
}
return run_real_main(real_args);
}
int action_verify_hashes(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Verify file backup hashes", ' ', cmdline_version);
TCLAP::SwitchArg delete_verify_failed_arg("d", "delete-verify-failed",
"Delete file entries of files with failed verification", cmd, false);
TCLAP::ValueArg<std::string> verify_arg("v", "verify",
"Specify file backup(s) to verify",
true, "all", "file backup set", cmd);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
if(delete_verify_failed_arg.getValue())
{
real_args.push_back("--delete_verify_failed");
real_args.push_back("true");
}
if(verify_arg.getValue()=="all")
{
real_args.push_back("--verify_hashes");
real_args.push_back("true");
}
else
{
real_args.push_back("--verify_hashes");
real_args.push_back(verify_arg.getValue());
}
return run_real_main(real_args);
}
int action_remove_unknown(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Remove unknown files and directories from backup storage and fix symbolic links in backup storage", ' ', cmdline_version);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--app");
real_args.push_back("remove_unknown");
return run_real_main(real_args);
}
int action_defrag_database(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Rebuild UrBackup database", ' ', cmdline_version);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--app");
real_args.push_back("defrag_database");
return run_real_main(real_args);
}
int action_repair_database(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Try to repair UrBackup database", ' ', cmdline_version);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--app");
real_args.push_back("repair_database");
return run_real_main(real_args);
}
int action_reset_pw(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Reset web interface administrator password", ' ', cmdline_version);
TCLAP::ValueArg<std::string> password_arg("p", "password",
"New administrator password",
true, "", "password", cmd);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--set_admin_pw");
real_args.push_back(password_arg.getValue());
return run_real_main(real_args);
}
int action_cleanup(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Cleanup file/image backups from backup storage", ' ', cmdline_version);
TCLAP::ValueArg<std::string> cleanup_amount_arg("a", "amount",
"Amount of storage to cleanup",
true, "", "%|M|G|T", cmd);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--app");
real_args.push_back("cleanup");
real_args.push_back("--cleanup_amount");
real_args.push_back(cleanup_amount_arg.getValue());
return run_real_main(real_args);
}
int action_export_auth_log(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Export authentication log to csv file", ' ', cmdline_version);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--workingdir");
real_args.push_back(VARDIR);
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--app");
real_args.push_back("export_auth_log");
return run_real_main(real_args);
}
std::string curr_dir()
{
char buf[4096];
char* cwd = _getcwd(buf, sizeof(buf));
if(cwd!=NULL)
{
return cwd;
}
else
{
return std::string();
}
}
std::string make_absolute(std::string fn)
{
std::string cdir = curr_dir();
bool is_absolute = (fn.empty() || fn[0]=='/');
if(!is_absolute && !cdir.empty())
{
fn = cdir + "/" + fn;
}
return fn;
}
int action_decompress_file(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Decompress UrBackup compressed file", ' ', cmdline_version);
TCLAP::ValueArg<std::string> file_arg("f", "file",
"File to decompress",
true, "", "path", cmd);
TCLAP::ValueArg<std::string> user_arg("u", "user",
"Change process to run as specific user",
false, "urbackup", "user", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--user");
real_args.push_back(user_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--decompress");
real_args.push_back(make_absolute(file_arg.getValue()));
return run_real_main(real_args);
}
#ifndef _WIN32
int action_mount_vhd(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Mount VHD file", ' ', cmdline_version);
TCLAP::ValueArg<std::string> file_arg("f", "file",
"VHD(z) file to mount",
true, "", "path", cmd);
TCLAP::ValueArg<std::string> mountpoint_arg("m", "mountpoint",
"Mount the VHD(z)-file at this mountpoint",
true, "", "path", cmd);
TCLAP::ValueArg<std::string> tempmount_arg("t", "tempmount",
"Use this directory as temporary mountpoint",
false, "", "path", cmd);
TCLAP::ValueArg<std::string> logfile_arg("l", "logfile",
"Specifies the log file name for the background VHD-reading process",
false, "/var/log/urbackup-fuse.log", "path", cmd);
cmd.parse(args);
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--logfile");
real_args.push_back(logfile_arg.getValue());
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--mount");
real_args.push_back(make_absolute(file_arg.getValue()));
std::string tmpmountpoint;
if(tempmount_arg.getValue().empty())
{
char *tmpdir=getenv("TMPDIR");
std::string stmpdir;
if(tmpdir==NULL )
stmpdir="/tmp";
else
stmpdir=tmpdir;
stmpdir=stmpdir+"/cps.XXXXXX";
char* made_tmpdir = mkdtemp(&stmpdir[0]);
if(made_tmpdir==NULL)
{
std::cout << "Error creating temporary directory " << stmpdir << std::endl;
exit(1);
}
tmpmountpoint = stmpdir;
}
else
{
tmpmountpoint = tempmount_arg.getValue();
}
real_args.push_back("--mountpoint");
real_args.push_back(tmpmountpoint);
std::cout << "Loading FUSE kernel module..." << std::endl;
system("modprobe fuse");
std::cout << "Starting VHD background process..." << std::endl;
size_t pid1;
if( (pid1=fork())==0 )
{
if(setsid()==-1)
{
perror("urbackupsrv");
exit(1);
}
if(fork()==0)
{
for (int i=getdtablesize();i>=0;--i) close(i);
int i=open("/dev/null",O_RDWR);
dup(i);
dup(i);
return run_real_main(real_args);
}
else
{
exit(0);
}
}
else
{
int status;
int rc = waitpid(pid1, &status, 0);
if(rc==-1)
{
perror("urbackupsrv");
exit(1);
}
}
std::cout << "Waiting for background process to become available..." << std::endl;
int64 starttime = get_time_ms();
while(get_time_ms()-starttime<20000)
{
if(FileExists(tmpmountpoint+"/volume"))
{
std::cout << "Mounting..." << std::endl;
int rc = system(("mount -v -o loop,ro \""+tmpmountpoint+"/volume\" \""+mountpoint_arg.getValue()).c_str());
if(rc!=0)
{
std::cout << "Mounting failed." << std::endl;
exit(1);
}
else
{
std::cout << "Mounted successfully." << std::endl;
exit(0);
}
}
usleep(100*1000);
}
std::cout << "Timeout while waiting for background process. Please see logfile (" << logfile_arg.getValue() << ") for error details." << std::endl;
exit(1);
}
#endif
int action_assemble(std::vector<std::string> args)
{
TCLAP::CmdLine cmd("Assemble VHD(Z) volumes into one disk VHD file", ' ', cmdline_version);
TCLAP::MultiArg<std::string> assemble_in_arg("a", "assemble-in",
"File to assemble into the output file",
true, "path", cmd);
TCLAP::ValueArg<std::string> assemble_out("o", "assemble-out",
"Location where disk VHD is written when assembling",
true, "", "path", cmd);
cmd.parse(args);
std::string assemble_input;
for(size_t i=0;i<assemble_in_arg.getValue().size();++i)
{
if(!assemble_input.empty())
{
assemble_input+=";";
}
assemble_input+=make_absolute(assemble_in_arg.getValue()[i]);
}
std::vector<std::string> real_args;
real_args.push_back(args[0]);
real_args.push_back("--no-server");
real_args.push_back("--loglevel");
real_args.push_back("debug");
real_args.push_back("--assemble");
real_args.push_back(assemble_input);
real_args.push_back("--output_file");
real_args.push_back(assemble_out.getValue());
return run_real_main(real_args);
}
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] <command> [<args>]" << std::endl;
std::cout << std::endl;
std::cout << "Get specific command help with " << cmd << " <command> --help" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " run" << std::endl;
std::cout << "\t\t" "Run UrBackup server" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " verify-hashes" << std::endl;
std::cout << "\t\t" "Verify file backup hashes" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " remove-unknown" << std::endl;
std::cout << "\t\t" "Remove unknown files and directories from backup storage and fix symbolic links in backup storage" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " reset-pw" << std::endl;
std::cout << "\t\t" "Reset web interface administrator password" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " cleanup" << std::endl;
std::cout << "\t\t" "Cleanup file/image backups from backup storage" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " repair-database" << std::endl;
std::cout << "\t\t" "Try to repair UrBackup database" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " defrag-database" << std::endl;
std::cout << "\t\t" "Rebuild UrBackup database" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " export-auth-log" << std::endl;
std::cout << "\t\t" "Export authentication log to csv file" << std::endl;
std::cout << std::endl;
std::cout << "\t" << cmd << " decompress-file" << std::endl;
std::cout << "\t\t" "Decompress UrBackup compressed file" << std::endl;
std::cout << std::endl;
#if !defined(_WIN32) && defined(WITH_FUSEPLUGIN)
std::cout << "\t" << cmd << " mount-vhd" << std::endl;
std::cout << "\t\t" "Mount VHD file" << std::endl;
std::cout << std::endl;
#endif
std::cout << "\t" "urbackupsrv assemble" << std::endl;
std::cout << "\t\t" "Assemble VHD(Z) volumes into one disk VHD file" << std::endl;
std::cout << std::endl;
}
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<std::string> actions;
std::vector<action_fun> action_funs;
actions.push_back("run");
action_funs.push_back(action_run);
actions.push_back("verify-hashes");
action_funs.push_back(action_verify_hashes);
actions.push_back("remove-unknown");
action_funs.push_back(action_remove_unknown);
actions.push_back("reset-pw");
action_funs.push_back(action_reset_pw);
actions.push_back("cleanup");
action_funs.push_back(action_cleanup);
actions.push_back("repair-database");
action_funs.push_back(action_repair_database);
actions.push_back("defrag-database");
action_funs.push_back(action_defrag_database);
actions.push_back("export-auth-log");
action_funs.push_back(action_export_auth_log);
actions.push_back("decompress-file");
action_funs.push_back(action_decompress_file);
#if !defined(_WIN32) && defined(WITH_FUSEPLUGIN)
actions.push_back("mount-vhd");
action_funs.push_back(action_mount_vhd);
#endif
actions.push_back("assemble");
action_funs.push_back(action_assemble);
bool has_help=false;
bool has_version=false;
size_t action_idx=std::string::npos;
std::vector<std::string> args;
args.push_back(argv[0]);
for(size_t i=1;i<argc;++i)
{
std::string arg = argv[i];
if(arg=="--help" || arg=="-h")
{
has_help=true;
}
if(arg=="--version" || arg=="-v")
{
has_version=true;
}
if(!arg.empty() && arg[0]=='-')
{
args.push_back(arg);
continue;
}
bool found_action=false;
for(size_t j=0;j<actions.size();++j)
{
if(next(actions[j], 0, arg))
{
if(action_idx!=std::string::npos)
{
action_help(argv[0]);
exit(1);
}
action_idx=j;
found_action=true;
}
}
if(!found_action)
{
args.push_back(arg);
}
}
if(action_idx==std::string::npos)
{
if(has_help)
{
action_help(argv[0]);
exit(1);
}
if(has_version)
{
show_version();
exit(1);
}
action_help(argv[0]);
exit(1);
}
try
{
args[0]+=" "+actions[action_idx];
int rc = action_funs[action_idx](args);
return rc;
}
catch (TCLAP::ArgException &e)
{
std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
return 1;
}
}