summaryrefslogtreecommitdiff
path: root/bin/bbackupctl/bbackupctl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bin/bbackupctl/bbackupctl.cpp')
-rw-r--r--bin/bbackupctl/bbackupctl.cpp260
1 files changed, 178 insertions, 82 deletions
diff --git a/bin/bbackupctl/bbackupctl.cpp b/bin/bbackupctl/bbackupctl.cpp
index 5b09b4b5..28c43b0d 100644
--- a/bin/bbackupctl/bbackupctl.cpp
+++ b/bin/bbackupctl/bbackupctl.cpp
@@ -1,4 +1,4 @@
-// distribution boxbackup-0.10 (svn version: 494)
+// distribution boxbackup-0.11rc1 (svn version: 2023_2024)
//
// Copyright (c) 2003 - 2006
// Ben Summers and contributors. All rights reserved.
@@ -66,16 +66,26 @@
#include "MemLeakFindOn.h"
+enum Command
+{
+ Default,
+ WaitForSyncStart,
+ WaitForSyncEnd,
+ SyncAndWaitForEnd,
+};
+
void PrintUsageAndExit()
{
printf("Usage: bbackupctl [-q] [-c config_file] <command>\n"
"Commands are:\n"
- " sync -- start a syncronisation run now\n"
- " force-sync -- force the start of a syncronisation run, "
+ " sync -- start a synchronisation (backup) run now\n"
+ " force-sync -- force the start of a synchronisation run, "
"even if SyncAllowScript says no\n"
" reload -- reload daemon configuration\n"
" terminate -- terminate daemon now\n"
" wait-for-sync -- wait until the next sync starts, then exit\n"
+ " wait-for-end -- wait until the next sync finishes, then exit\n"
+ " sync-and-wait -- start sync, wait until it finishes, then exit\n"
);
exit(1);
}
@@ -84,17 +94,23 @@ int main(int argc, const char *argv[])
{
int returnCode = 0;
-#if defined WIN32 && ! defined NDEBUG
- ::openlog("Box Backup (bbackupctl)", 0, 0);
-#endif
-
MAINHELPER_SETUP_MEMORY_LEAK_EXIT_REPORT("bbackupctl.memleaks",
"bbackupctl")
MAINHELPER_START
- // Filename for configuraiton file?
- const char *configFilename = BOX_FILE_BBACKUPD_DEFAULT_CONFIG;
+#if defined WIN32 && ! defined NDEBUG
+ ::openlog("Box Backup (bbackupctl)", 0, 0);
+#endif
+
+ // Filename for configuration file?
+ std::string configFilename;
+
+ #ifdef WIN32
+ configFilename = BOX_GET_DEFAULT_BBACKUPD_CONFIG_FILE;
+ #else
+ configFilename = BOX_FILE_BBACKUPD_DEFAULT_CONFIG;
+ #endif
// Quiet?
bool quiet = false;
@@ -131,12 +147,16 @@ int main(int argc, const char *argv[])
}
// Read in the configuration file
- if(!quiet) printf("Using configuration file %s\n", configFilename);
+ if(!quiet) BOX_NOTICE("Using configuration file " << configFilename);
+
std::string errs;
- std::auto_ptr<Configuration> config(Configuration::LoadAndVerify(configFilename, &BackupDaemonConfigVerify, errs));
+ std::auto_ptr<Configuration> config(
+ Configuration::LoadAndVerify
+ (configFilename, &BackupDaemonConfigVerify, errs));
+
if(config.get() == 0 || !errs.empty())
{
- printf("Invalid configuration file:\n%s", errs.c_str());
+ BOX_ERROR("Invalid configuration file: " << errs);
return 1;
}
// Easier coding
@@ -145,7 +165,10 @@ int main(int argc, const char *argv[])
// Check there's a socket defined in the config file
if(!conf.KeyExists("CommandSocket"))
{
- printf("Daemon isn't using a control socket, could not execute command.\nAdd a CommandSocket declaration to the bbackupd.conf file.\n");
+ BOX_ERROR("Daemon isn't using a control socket, "
+ "could not execute command.\n"
+ "Add a CommandSocket declaration to the "
+ "bbackupd.conf file.");
return 1;
}
@@ -160,25 +183,22 @@ int main(int argc, const char *argv[])
try
{
#ifdef WIN32
- connection.Connect(BOX_NAMED_PIPE_NAME);
+ std::string socket = conf.GetKeyValue("CommandSocket");
+ connection.Connect(socket);
#else
connection.Open(Socket::TypeUNIX, conf.GetKeyValue("CommandSocket").c_str());
#endif
}
catch(...)
{
- printf("Failed to connect to daemon control socket.\n"
+ BOX_ERROR("Failed to connect to daemon control socket.\n"
"Possible causes:\n"
" * Daemon not running\n"
" * Daemon busy syncing with store server\n"
" * Another bbackupctl process is communicating with the daemon\n"
- " * Daemon is waiting to recover from an error\n"
+ " * Daemon is waiting to recover from an error"
);
-#if defined WIN32 && ! defined NDEBUG
- syslog(LOG_ERR,"Failed to connect to the command socket");
-#endif
-
return 1;
}
@@ -189,29 +209,16 @@ int main(int argc, const char *argv[])
std::string configSummary;
if(!getLine.GetLine(configSummary))
{
-#if defined WIN32 && ! defined NDEBUG
- syslog(LOG_ERR, "Failed to receive configuration summary "
+ BOX_ERROR("Failed to receive configuration summary "
"from daemon");
-#else
- printf("Failed to receive configuration summary from daemon\n");
-#endif
-
return 1;
}
// Was the connection rejected by the server?
if(getLine.IsEOF())
{
-#if defined WIN32 && ! defined NDEBUG
- syslog(LOG_ERR, "Server rejected the connection. "
- "Are you running bbackupctl as the same user "
- "as the daemon?");
-#else
- printf("Server rejected the connection. "
- "Are you running bbackupctl as the same user "
- "as the daemon?\n");
-#endif
-
+ BOX_ERROR("Server rejected the connection. Are you running "
+ "bbackupctl as the same user as the daemon?");
return 1;
}
@@ -220,74 +227,163 @@ int main(int argc, const char *argv[])
if(::sscanf(configSummary.c_str(), "bbackupd: %d %d %d %d", &autoBackup,
&updateStoreInterval, &minimumFileAge, &maxUploadWait) != 4)
{
- printf("Config summary didn't decode\n");
+ BOX_ERROR("Config summary didn't decode.");
return 1;
}
// Print summary?
if(!quiet)
{
- printf("Daemon configuration summary:\n" \
- " AutomaticBackup = %s\n" \
- " UpdateStoreInterval = %d seconds\n" \
- " MinimumFileAge = %d seconds\n" \
- " MaxUploadWait = %d seconds\n",
- autoBackup?"true":"false", updateStoreInterval, minimumFileAge, maxUploadWait);
+ BOX_INFO("Daemon configuration summary:\n"
+ " AutomaticBackup = " <<
+ (autoBackup?"true":"false") << "\n"
+ " UpdateStoreInterval = " << updateStoreInterval <<
+ " seconds\n"
+ " MinimumFileAge = " << minimumFileAge << " seconds\n"
+ " MaxUploadWait = " << maxUploadWait << " seconds");
}
- // Is the command the "wait for sync to start" command?
- bool areWaitingForSync = false;
- if(::strcmp(argv[0], "wait-for-sync") == 0)
+ std::string stateLine;
+ if(!getLine.GetLine(stateLine) || getLine.IsEOF())
{
- // Check that it's not in non-automatic mode, because then it'll never start
- if(!autoBackup)
- {
- printf("ERROR: Daemon is not in automatic mode -- sync will never start!\n");
- return 1;
- }
-
- // Yes... set the flag so we know what we're waiting for a sync to start
- areWaitingForSync = true;
+ BOX_ERROR("Failed to receive state line from daemon");
+ return 1;
+ }
+
+ // Decode it
+ int currentState;
+ if(::sscanf(stateLine.c_str(), "state %d", &currentState) != 1)
+ {
+ BOX_ERROR("Received invalid state line from daemon");
+ return 1;
+ }
+
+ Command command = Default;
+ std::string commandName(argv[0]);
+
+ if (commandName == "wait-for-sync")
+ {
+ command = WaitForSyncStart;
}
- else
+ else if (commandName == "wait-for-end")
{
- // No? Just send the command given plus a quit command.
- std::string cmd(argv[0]);
- cmd += "\nquit\n";
- connection.Write(cmd.c_str(), cmd.size());
+ command = WaitForSyncEnd;
+ }
+ else if (commandName == "sync-and-wait")
+ {
+ command = SyncAndWaitForEnd;
+ }
+
+ switch (command)
+ {
+ case WaitForSyncStart:
+ case WaitForSyncEnd:
+ {
+ // Check that it's in automatic mode,
+ // because otherwise it'll never start
+
+ if(!autoBackup)
+ {
+ BOX_ERROR("Daemon is not in automatic mode, "
+ "sync will never start!");
+ return 1;
+ }
+
+ }
+ break;
+
+ case SyncAndWaitForEnd:
+ {
+ // send a sync command
+ std::string cmd("force-sync\n");
+ connection.Write(cmd.c_str(), cmd.size());
+ connection.WriteAllBuffered();
+
+ if (currentState != 0)
+ {
+ BOX_INFO("Waiting for current sync/error state "
+ "to finish...");
+ }
+ }
+ break;
+
+ default:
+ {
+ // Normal case, just send the command given
+ // plus a quit command.
+ std::string cmd = commandName;
+ cmd += "\nquit\n";
+ connection.Write(cmd.c_str(), cmd.size());
+ }
}
// Read the response
std::string line;
- while(!getLine.IsEOF() && getLine.GetLine(line))
+ bool syncIsRunning = false;
+ bool finished = false;
+
+ while(!finished && !getLine.IsEOF() && getLine.GetLine(line))
{
- if(areWaitingForSync)
+ switch (command)
{
- // Need to wait for the state change...
- if(line == "start-sync")
+ case WaitForSyncStart:
{
- // Send a quit command to finish nicely
- connection.Write("quit\n", 5);
-
- // And we're done
- break;
- }
- }
- else
- {
- // Is this an OK or error line?
- if(line == "ok")
+ // Need to wait for the state change...
+ if(line == "start-sync")
+ {
+ // Send a quit command to finish nicely
+ connection.Write("quit\n", 5);
+
+ // And we're done
+ finished = true;
+ }
+ }
+ break;
+
+ case WaitForSyncEnd:
+ case SyncAndWaitForEnd:
{
- if(!quiet)
+ if(line == "start-sync")
+ {
+ if (!quiet) BOX_INFO("Sync started...");
+ syncIsRunning = true;
+ }
+ else if(line == "finish-sync")
{
- printf("Succeeded.\n");
+ if (syncIsRunning)
+ {
+ if (!quiet) BOX_INFO("Sync finished.");
+ // Send a quit command to finish nicely
+ connection.Write("quit\n", 5);
+
+ // And we're done
+ finished = true;
+ }
+ else
+ {
+ if (!quiet) BOX_INFO("Previous sync finished.");
+ }
+ // daemon must still be busy
}
- break;
}
- else if(line == "error")
+ break;
+
+ default:
{
- printf("ERROR. (Check command spelling)\n");
- returnCode = 1;
- break;
+ // Is this an OK or error line?
+ if(line == "ok")
+ {
+ if(!quiet)
+ {
+ BOX_INFO("Succeeded.");
+ }
+ finished = true;
+ }
+ else if(line == "error")
+ {
+ BOX_ERROR("Check command spelling");
+ returnCode = 1;
+ finished = true;
+ }
}
}
}