diff options
Diffstat (limited to 'bin/bbackupctl/bbackupctl.cpp')
-rw-r--r-- | bin/bbackupctl/bbackupctl.cpp | 260 |
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", ¤tState) != 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; + } } } } |