summaryrefslogtreecommitdiff
path: root/bin/bbackupctl
diff options
context:
space:
mode:
Diffstat (limited to 'bin/bbackupctl')
-rw-r--r--bin/bbackupctl/bbackupctl.cpp202
1 files changed, 154 insertions, 48 deletions
diff --git a/bin/bbackupctl/bbackupctl.cpp b/bin/bbackupctl/bbackupctl.cpp
index dfadc37d..6f7c55f7 100644
--- a/bin/bbackupctl/bbackupctl.cpp
+++ b/bin/bbackupctl/bbackupctl.cpp
@@ -28,16 +28,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);
}
@@ -107,7 +117,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");
+ printf("Daemon isn't using a control socket, "
+ "could not execute command.\n"
+ "Add a CommandSocket declaration to the "
+ "bbackupd.conf file.\n");
return 1;
}
@@ -188,68 +201,161 @@ int main(int argc, const char *argv[])
// 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);
+ 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);
}
- // 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;
+#if defined WIN32 && ! defined NDEBUG
+ syslog(LOG_ERR, "Failed to receive state line from daemon");
+#else
+ printf("Failed to receive state line from daemon\n");
+#endif
+ return 1;
+ }
+
+ // Decode it
+ int currentState;
+ if(::sscanf(stateLine.c_str(), "state %d", &currentState) != 1)
+ {
+ printf("State line didn't decode\n");
+ return 1;
}
- else
+
+ Command command = Default;
+ std::string commandName(argv[0]);
+
+ if (commandName == "wait-for-sync")
+ {
+ command = WaitForSyncStart;
+ }
+ 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 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;
+ }
+
+ }
+ 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)
+ {
+ printf("Waiting for current sync/error state "
+ "to finish...\n");
+ }
+ }
+ 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) printf("Sync started...\n");
+ syncIsRunning = true;
+ }
+ else if(line == "finish-sync")
{
- printf("Succeeded.\n");
+ if (syncIsRunning)
+ {
+ if (!quiet) printf("Sync finished.\n");
+ // Send a quit command to finish nicely
+ connection.Write("quit\n", 5);
+
+ // And we're done
+ finished = true;
+ }
+ else
+ {
+ if (!quiet) printf("Previous sync finished.\n");
+ }
+ // 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)
+ {
+ printf("Succeeded.\n");
+ }
+ finished = true;
+ }
+ else if(line == "error")
+ {
+ printf("ERROR. (Check command spelling)\n");
+ returnCode = 1;
+ finished = true;
+ }
}
}
}