diff options
author | Ben Summers <ben@fluffy.co.uk> | 2006-02-13 13:30:21 +0000 |
---|---|---|
committer | Ben Summers <ben@fluffy.co.uk> | 2006-02-13 13:30:21 +0000 |
commit | 830aa82e44381c85d8486e46de7ae0e26830457e (patch) | |
tree | f29edb3c3013990a3ae758e1ccfdb56a2d20923f /bin | |
parent | 2edd0a00e3244cc4dbc369d81ed1748768a06fb8 (diff) |
Merge chris/win32/vc2005-compile-fixes @ r455, add infrastructure/msvc to distribution
Diffstat (limited to 'bin')
-rw-r--r-- | bin/bbackupctl/bbackupctl.cpp | 7 | ||||
-rw-r--r-- | bin/bbackupd/BackupClientContext.cpp | 14 | ||||
-rw-r--r-- | bin/bbackupd/BackupClientContext.h | 5 | ||||
-rw-r--r-- | bin/bbackupd/BackupClientDirectoryRecord.cpp | 5 | ||||
-rw-r--r-- | bin/bbackupd/BackupDaemon.cpp | 216 | ||||
-rw-r--r-- | bin/bbackupd/BackupDaemon.h | 5 | ||||
-rw-r--r-- | bin/bbackupd/Win32ServiceFunctions.cpp | 69 | ||||
-rw-r--r-- | bin/bbackupd/bbackupd.cpp | 12 | ||||
-rw-r--r-- | bin/bbackupquery/BackupQueries.cpp | 322 | ||||
-rw-r--r-- | bin/bbackupquery/bbackupquery.cpp | 56 |
10 files changed, 515 insertions, 196 deletions
diff --git a/bin/bbackupctl/bbackupctl.cpp b/bin/bbackupctl/bbackupctl.cpp index d39092e8..dfadc37d 100644 --- a/bin/bbackupctl/bbackupctl.cpp +++ b/bin/bbackupctl/bbackupctl.cpp @@ -10,7 +10,10 @@ #include "Box.h" #include <stdio.h> -#include <unistd.h> + +#ifdef HAVE_UNISTD_H + #include <unistd.h> +#endif #include "MainHelper.h" #include "BoxPortsAndFiles.h" @@ -212,7 +215,7 @@ int main(int argc, const char *argv[]) // 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()); + connection.Write(cmd.c_str(), cmd.size()); } // Read the response diff --git a/bin/bbackupd/BackupClientContext.cpp b/bin/bbackupd/BackupClientContext.cpp index ae4e1cad..25852b19 100644 --- a/bin/bbackupd/BackupClientContext.cpp +++ b/bin/bbackupd/BackupClientContext.cpp @@ -57,9 +57,7 @@ BackupClientContext::BackupClientContext(BackupDaemon &rDaemon, TLSContext &rTLS mpExcludeFiles(0), mpExcludeDirs(0), mbIsManaged(false), - mTimeMgmtEpoch(0), - mMaximumDiffTime(600), - mKeepAliveTime(0) + mTimeMgmtEpoch(0) { } @@ -511,6 +509,9 @@ void BackupClientContext::ManageDiffProcess() #ifdef PLATFORM_CYGWIN ::signal(SIGALRM, TimerSigHandler); +#elif defined WIN32 + // no support for SIGVTALRM + SetTimerHandler(TimerSigHandler); #else ::signal(SIGVTALRM, TimerSigHandler); #endif // PLATFORM_CYGWIN @@ -599,7 +600,10 @@ void BackupClientContext::UnManageDiffProcess() void BackupClientContext::DoKeepAlive() { if (!mpConnection) + { + ::syslog(LOG_ERR, "DoKeepAlive() called with no connection!"); return; + } mpConnection->QueryGetIsAlive(); } @@ -620,10 +624,10 @@ time_t BackupClientContext::GetTimeMgmtEpoch() int BackupClientContext::GetMaximumDiffingTime() { - return mMaximumDiffTime; + return sMaximumDiffTime; } int BackupClientContext::GetKeepaliveTime() { - return mKeepAliveTime; + return sKeepAliveTime; } diff --git a/bin/bbackupd/BackupClientContext.h b/bin/bbackupd/BackupClientContext.h index 234868db..a0cf6e1f 100644 --- a/bin/bbackupd/BackupClientContext.h +++ b/bin/bbackupd/BackupClientContext.h @@ -208,11 +208,6 @@ private: bool mbIsManaged; // unix time when diff was started time_t mTimeMgmtEpoch; - // maximum time to spend diffing, in seconds - int mMaximumDiffTime; - // maximum time of SSL inactivity (keep-alive interval), in seconds - int mKeepAliveTime; - }; diff --git a/bin/bbackupd/BackupClientDirectoryRecord.cpp b/bin/bbackupd/BackupClientDirectoryRecord.cpp index 49193ccf..5a566d84 100644 --- a/bin/bbackupd/BackupClientDirectoryRecord.cpp +++ b/bin/bbackupd/BackupClientDirectoryRecord.cpp @@ -9,7 +9,10 @@ #include "Box.h" -#include <dirent.h> +#ifdef HAVE_DIRENT_H + #include <dirent.h> +#endif + #include <errno.h> #include <string.h> diff --git a/bin/bbackupd/BackupDaemon.cpp b/bin/bbackupd/BackupDaemon.cpp index a6d25f0f..01e5bf36 100644 --- a/bin/bbackupd/BackupDaemon.cpp +++ b/bin/bbackupd/BackupDaemon.cpp @@ -11,8 +11,10 @@ #include <stdio.h> #include <string.h> -#include <unistd.h> +#ifdef HAVE_UNISTD_H + #include <unistd.h> +#endif #ifdef HAVE_SIGNAL_H #include <signal.h> #endif @@ -35,6 +37,9 @@ #include <cstdio> #include <sys/mnttab.h> #endif +#ifdef HAVE_PROCESS_H + #include <process.h> +#endif #include "Configuration.h" #include "IOStream.h" @@ -78,6 +83,25 @@ static const time_t MAX_SLEEP_TIME = 1024; // This prevents repetative cycles of load on the server #define SYNC_PERIOD_RANDOM_EXTRA_TIME_SHIFT_BY 6 +#ifdef WIN32 +// -------------------------------------------------------------------------- +// +// Function +// Name: HelperThread() +// Purpose: Background thread function, called by Windows, +// calls the BackupDaemon's RunHelperThread method +// to listen for and act on control communications +// Created: 18/2/04 +// +// -------------------------------------------------------------------------- +unsigned int WINAPI HelperThread(LPVOID lpParam) +{ + ((BackupDaemon *)lpParam)->RunHelperThread(); + + return 0; +} +#endif + // -------------------------------------------------------------------------- // // Function @@ -99,6 +123,20 @@ BackupDaemon::BackupDaemon() { mNotificationsSent[l] = false; } + +#ifdef WIN32 + // Create a thread to handle the named pipe + HANDLE hThread; + unsigned int dwThreadId; + + hThread = (HANDLE) _beginthreadex( + NULL, // default security attributes + 0, // use default stack size + HelperThread, // thread function + this, // argument to thread function + 0, // use default creation flags + &dwThreadId); // returns the thread identifier +#endif } // -------------------------------------------------------------------------- @@ -185,11 +223,12 @@ void BackupDaemon::SetupInInitialProcess() if(GetConfiguration().KeyExists("CommandSocket")) { printf( - "============================================================================================\n" \ - "SECURITY WARNING: This platform cannot check the credentials of connections to the\n" \ - "command socket. This is a potential DoS security problem.\n" \ - "Remove the CommandSocket directive from the bbackupd.conf file if bbackupctl is not used.\n" \ - "============================================================================================\n" + "==============================================================================\n" + "SECURITY WARNING: This platform cannot check the credentials of connections to\n" + "the command socket. This is a potential DoS security problem.\n" + "Remove the CommandSocket directive from the bbackupd.conf file if bbackupctl\n" + "is not used.\n" + "==============================================================================\n" ); } } @@ -221,30 +260,13 @@ void BackupDaemon::DeleteAllLocations() } #ifdef WIN32 -// -------------------------------------------------------------------------- -// -// Function -// Name: HelperThread() -// Purpose: Background thread function, called by Windows, -// calls the BackupDaemon's RunHelperThread method -// to listen for and act on control communications -// Created: 18/2/04 -// -// -------------------------------------------------------------------------- -unsigned int WINAPI HelperThread( LPVOID lpParam ) -{ - printf( "Parameter = %lu.\n", *(DWORD*)lpParam ); - ((BackupDaemon *)lpParam)->RunHelperThread(); - - return 0; -} - void BackupDaemon::RunHelperThread(void) { mpCommandSocketInfo = new CommandSocketInfo; this->mReceivedCommandConn = false; - while ( !IsTerminateWanted() ) + // loop until the parent process exits + while (TRUE) { try { @@ -359,24 +381,21 @@ void BackupDaemon::RunHelperThread(void) void BackupDaemon::Run() { #ifdef WIN32 - - // Create a thread to handle the named pipe - HANDLE hThread; - unsigned int dwThreadId; - - hThread = (HANDLE) _beginthreadex( - NULL, // default security attributes - 0, // use default stack size - HelperThread, // thread function - this, // argument to thread function - 0, // use default creation flags - &dwThreadId); // returns the thread identifier - // init our own timer for file diff timeouts InitTimer(); -#else // ! WIN32 + try + { + Run2(); + } + catch(...) + { + FiniTimer(); + throw; + } + FiniTimer(); +#else // ! WIN32 // Ignore SIGPIPE (so that if a command connection is broken, the daemon doesn't terminate) ::signal(SIGPIPE, SIG_IGN); @@ -390,8 +409,6 @@ void BackupDaemon::Run() ::unlink(socketName); mpCommandSocketInfo->mListeningSocket.Listen(Socket::TypeUNIX, socketName); } - -#endif // WIN32 // Handle things nicely on exceptions try @@ -402,23 +419,28 @@ void BackupDaemon::Run() { if(mpCommandSocketInfo != 0) { - delete mpCommandSocketInfo; + try + { + delete mpCommandSocketInfo; + } + catch(...) + { + ::syslog(LOG_WARNING, + "Error closing command socket " + "after exception, ignored."); + } mpCommandSocketInfo = 0; } throw; } - + // Clean up if(mpCommandSocketInfo != 0) { delete mpCommandSocketInfo; mpCommandSocketInfo = 0; } - -#ifdef WIN32 - // clean up windows specific stuff. - FiniTimer(); #endif } @@ -482,8 +504,8 @@ void BackupDaemon::Run2() BackupClientContext::ClientStoreMarker_NotKnown; // haven't contacted the store yet - DeserializeStoreObjectInfo(clientStoreMarker, lastSyncTime, - nextSyncTime); + bool deserialised = DeserializeStoreObjectInfo(clientStoreMarker, + lastSyncTime, nextSyncTime); // -------------------------------------------------------------------------------------------- @@ -585,6 +607,17 @@ void BackupDaemon::Run2() // but this should be OK, because the changes only upload should upload no data. syncPeriodEndExtended += SecondsToBoxTime((time_t)(356*24*3600)); } + + // Delete the serialised store object file, + // so that we don't try to reload it after a + // partially completed backup + if(deserialised && !DeleteStoreObjectInfo()) + { + ::syslog(LOG_ERR, "Failed to delete the " + "StoreObjectInfoFile, backup cannot " + "continue safely."); + continue; + } // Do sync bool errorOccurred = false; @@ -751,7 +784,12 @@ void BackupDaemon::Run2() "to retry...", errorString, errorCode, errorSubCode); - ::sleep(100); + ::sleep(10); + nextSyncTime = currentSyncStartTime + + SecondsToBoxTime(90) + + Random::RandomInt( + updateStoreInterval >> + SYNC_PERIOD_RANDOM_EXTRA_TIME_SHIFT_BY); } } @@ -863,7 +901,7 @@ void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFla #ifdef WIN32 // Really could use some interprocess protection, mutex etc // any side effect should be too bad???? :) - DWORD timeout = BoxTimeToMilliSeconds(RequiredDelay); + DWORD timeout = (DWORD)BoxTimeToMilliSeconds(RequiredDelay); while ( this->mReceivedCommandConn == false ) { @@ -1065,25 +1103,23 @@ void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFla // -------------------------------------------------------------------------- void BackupDaemon::CloseCommandConnection() { +#ifndef WIN32 try { TRACE0("Closing command connection\n"); -#ifdef WIN32 - mpCommandSocketInfo->mListeningSocket.Close(); -#else if(mpCommandSocketInfo->mpGetLine) { delete mpCommandSocketInfo->mpGetLine; mpCommandSocketInfo->mpGetLine = 0; } mpCommandSocketInfo->mpConnectedSocket.reset(); -#endif } catch(...) { // Ignore any errors } +#endif } @@ -1100,7 +1136,11 @@ void BackupDaemon::SendSyncStartOrFinish(bool SendStart) { // The bbackupctl program can't rely on a state change, because it may never // change if the server doesn't need to be contacted. - + +#ifdef __MINGW32__ +#warning race condition: what happens if socket is closed? +#endif + if (mpCommandSocketInfo != NULL && #ifdef WIN32 mpCommandSocketInfo->mListeningSocket.IsConnected() @@ -1114,7 +1154,7 @@ void BackupDaemon::SendSyncStartOrFinish(bool SendStart) { #ifdef WIN32 mpCommandSocketInfo->mListeningSocket.Write(message, - strlen(message)); + (int)strlen(message)); #else mpCommandSocketInfo->mpConnectedSocket->Write(message, strlen(message)); @@ -1711,7 +1751,10 @@ void BackupDaemon::SetState(int State) char newStateSize = sprintf(newState, "state %d\n", State); #ifdef WIN32 - #warning FIX ME: race condition + #ifndef _MSC_VER + #warning FIX ME: race condition + #endif + // what happens if the socket is closed by the other thread before // we can write to it? Null pointer deref at best. if (mpCommandSocketInfo && @@ -2196,7 +2239,7 @@ void BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time // Created: 2005/04/11 // // -------------------------------------------------------------------------- -void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime) +bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime) { // // @@ -2208,7 +2251,7 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ // if(!GetConfiguration().KeyExists("StoreObjectInfoFile")) { - return; + return false; } std::string StoreObjectInfoFile = @@ -2216,7 +2259,7 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ if (StoreObjectInfoFile.size() <= 0) { - return; + return false; } try @@ -2236,7 +2279,7 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ "is not a valid or compatible serialised " "archive. Will re-cache from store.", StoreObjectInfoFile.c_str()); - return; + return false; } // @@ -2251,7 +2294,7 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ "is not a valid or compatible serialised " "archive. Will re-cache from store.", StoreObjectInfoFile.c_str()); - return; + return false; } // @@ -2264,11 +2307,11 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ if (iVersion != STOREOBJECTINFO_VERSION) { ::syslog(LOG_WARNING, "Store object info file '%s' " - "version [%d] unsupported. " + "version %d unsupported. " "Will re-cache from store.", StoreObjectInfoFile.c_str(), iVersion); - return; + return false; } // @@ -2283,7 +2326,7 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ ::syslog(LOG_WARNING, "Store object info file '%s' " "out of date. Will re-cache from store", StoreObjectInfoFile.c_str()); - return; + return false; } // @@ -2331,12 +2374,7 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ "version [%d]", StoreObjectInfoFile.c_str(), iVersion); - if (::unlink(StoreObjectInfoFile.c_str()) != 0) - { - ::syslog(LOG_ERR, "Failed to delete the old " - "store object info file '%s': %s", - StoreObjectInfoFile.c_str(), strerror(errno)); - } + return true; } catch (...) { @@ -2352,4 +2390,38 @@ void BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ "Will re-cache from store.", StoreObjectInfoFile.c_str()); } + + return false; +} + +// -------------------------------------------------------------------------- +// +// Function +// Name: BackupDaemon::DeleteStoreObjectInfo() +// Purpose: Deletes the serialised state file, to prevent us +// from using it again if a backup is interrupted. +// +// Created: 2006/02/12 +// +// -------------------------------------------------------------------------- + +bool BackupDaemon::DeleteStoreObjectInfo() const +{ + if(!GetConfiguration().KeyExists("StoreObjectInfoFile")) + { + return false; + } + + std::string StoreObjectInfoFile = + GetConfiguration().GetKeyValue("StoreObjectInfoFile"); + + if (::unlink(StoreObjectInfoFile.c_str()) != 0) + { + ::syslog(LOG_ERR, "Failed to delete the old " + "store object info file '%s': %s", + StoreObjectInfoFile.c_str(), strerror(errno)); + return false; + } + + return true; } diff --git a/bin/bbackupd/BackupDaemon.h b/bin/bbackupd/BackupDaemon.h index 8693fe9e..3bd15fad 100644 --- a/bin/bbackupd/BackupDaemon.h +++ b/bin/bbackupd/BackupDaemon.h @@ -45,10 +45,11 @@ public: BackupDaemon(); ~BackupDaemon(); +private: // methods below do partial (specialized) serialization of client state only void SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const; - void DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime); -private: + bool DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_time_t & theLastSyncTime, box_time_t & theNextSyncTime); + bool DeleteStoreObjectInfo() const; BackupDaemon(const BackupDaemon &); public: diff --git a/bin/bbackupd/Win32ServiceFunctions.cpp b/bin/bbackupd/Win32ServiceFunctions.cpp index 89f02f62..b74c7e09 100644 --- a/bin/bbackupd/Win32ServiceFunctions.cpp +++ b/bin/bbackupd/Win32ServiceFunctions.cpp @@ -14,10 +14,12 @@ #include "Box.h" -//#include <stdio.h> -//#include <stdlib.h> -#include <unistd.h> -//#include <windows.h> +#ifdef HAVE_UNISTD_H + #include <unistd.h> +#endif +#ifdef HAVE_PROCESS_H + #include <process.h> +#endif extern void TerminateService(void); extern unsigned int WINAPI RunService(LPVOID lpParameter); @@ -31,18 +33,23 @@ HANDLE gStopServiceEvent = 0; #define SERVICE_NAME "boxbackup" +void ShowMessage(char *s) +{ + MessageBox(0, s, "Box Backup Message", + MB_OK | MB_SETFOREGROUND | MB_DEFAULT_DESKTOP_ONLY); +} + void ErrorHandler(char *s, DWORD err) { char buf[256]; memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf)-1, "%s (%d)", s, err); + _snprintf(buf, sizeof(buf)-1, "%s (%d)", s, err); ::syslog(LOG_ERR, "%s", buf); MessageBox(0, buf, "Error", MB_OK | MB_SETFOREGROUND | MB_DEFAULT_DESKTOP_ONLY); ExitProcess(err); } - void WINAPI ServiceControlHandler( DWORD controlCode ) { switch ( controlCode ) @@ -88,7 +95,7 @@ void WINAPI ServiceControlHandler( DWORD controlCode ) VOID ServiceMain(DWORD argc, LPTSTR *argv) { - // initialise service status + // initialise service status gServiceStatus.dwServiceType = SERVICE_WIN32; gServiceStatus.dwCurrentState = SERVICE_STOPPED; gServiceStatus.dwControlsAccepted = 0; @@ -178,14 +185,19 @@ void InstallService(void) scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE); - if (!scm) return; + if (!scm) + { + syslog(LOG_ERR, "Failed to open service control manager: " + "error %d", GetLastError()); + return; + } char cmd[MAX_PATH]; GetModuleFileName(NULL, cmd, sizeof(cmd)-1); cmd[sizeof(cmd)-1] = 0; char cmd_args[MAX_PATH]; - snprintf(cmd_args, sizeof(cmd_args)-1, "%s --service", cmd); + _snprintf(cmd_args, sizeof(cmd_args)-1, "%s --service", cmd); cmd_args[sizeof(cmd_args)-1] = 0; newService = CreateService( @@ -194,12 +206,31 @@ void InstallService(void) "Box Backup", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, + SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, cmd_args, 0,0,0,0,0); - if (newService) CloseServiceHandle(newService); + if (!newService) + { + ::syslog(LOG_ERR, "Failed to create Box Backup service: " + "error %d", GetLastError()); + return; + } + + ::syslog(LOG_INFO, "Created Box Backup service"); + + SERVICE_DESCRIPTION desc; + desc.lpDescription = "Backs up your data files over the Internet"; + + if (!ChangeServiceConfig2(newService, SERVICE_CONFIG_DESCRIPTION, + &desc)) + { + ::syslog(LOG_WARNING, "Failed to set description for " + "Box Backup service: error %d", GetLastError()); + } + + CloseServiceHandle(newService); CloseServiceHandle(scm); } @@ -210,23 +241,31 @@ void RemoveService(void) scm = OpenSCManager(0,0,SC_MANAGER_CREATE_SERVICE); - if (!scm) return; + if (!scm) + { + syslog(LOG_ERR, "Failed to open service control manager: " + "error %d", GetLastError()); + return; + } service = OpenService(scm, SERVICE_NAME, SERVICE_ALL_ACCESS|DELETE); ControlService(service, SERVICE_CONTROL_STOP, &status); if (!service) { - printf("Failed to open service manager"); + syslog(LOG_ERR, "Failed to open Box Backup service: " + "error %d", GetLastError()); return; } + if (DeleteService(service)) { - printf("Service removed"); + syslog(LOG_INFO, "Box Backup service deleted"); } else { - printf("Failed to remove service"); + syslog(LOG_ERR, "Failed to remove Box Backup service: " + "error %d", GetLastError()); } CloseServiceHandle(service); diff --git a/bin/bbackupd/bbackupd.cpp b/bin/bbackupd/bbackupd.cpp index 1c870317..089b2d09 100644 --- a/bin/bbackupd/bbackupd.cpp +++ b/bin/bbackupd/bbackupd.cpp @@ -48,13 +48,19 @@ int main(int argc, const char *argv[]) InstallService(); return 0; } - + + bool runAsWin32Service = false; + if (argc == 2 && ::strcmp(argv[1], "--service") == 0) + { + runAsWin32Service = true; + } + // Under win32 we must initialise the Winsock library // before using sockets WSADATA info; - if (WSAStartup(MAKELONG(1, 1), &info) == SOCKET_ERROR) + if (WSAStartup(0x0101, &info) == SOCKET_ERROR) { // box backup will not run without sockets ::syslog(LOG_ERR, "Failed to initialise Windows Sockets"); @@ -65,7 +71,7 @@ int main(int argc, const char *argv[]) int ExitCode = 0; - if (argc == 2 && ::strcmp(argv[1], "--service") == 0) + if (runAsWin32Service) { syslog(LOG_INFO,"Starting Box Backup Service"); OurService(); diff --git a/bin/bbackupquery/BackupQueries.cpp b/bin/bbackupquery/BackupQueries.cpp index 473daaf6..916228c3 100644 --- a/bin/bbackupquery/BackupQueries.cpp +++ b/bin/bbackupquery/BackupQueries.cpp @@ -9,15 +9,21 @@ #include "Box.h" +#ifdef HAVE_UNISTD_H + #include <unistd.h> +#endif + #include <string.h> #include <stdio.h> -#include <unistd.h> #include <errno.h> #include <stdlib.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> -#include <dirent.h> + +#ifdef HAVE_DIRENT_H + #include <dirent.h> +#endif #include <set> @@ -246,8 +252,9 @@ void BackupQueries::DoCommand(const char *Command) case COMMAND_pwd: { // Simple implementation, so do it here - std::string dir(GetCurrentDirectoryName()); - printf("%s (%08llx)\n", dir.c_str(), GetCurrentDirectoryID()); + printf("%s (%08llx)\n", + GetCurrentDirectoryName().c_str(), + (long long)GetCurrentDirectoryID()); } break; @@ -325,11 +332,23 @@ void BackupQueries::CommandList(const std::vector<std::string> &args, const bool // Got a directory in the arguments? if(args.size() > 0) { +#ifdef WIN32 + std::string storeDirEncoded; + if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) + return; +#else + const std::string& storeDirEncoded(args[0]); +#endif + // Attempt to find the directory - rootDir = FindDirectoryObjectID(args[0], opts[LIST_OPTION_ALLOWOLD], opts[LIST_OPTION_ALLOWDELETED]); + rootDir = FindDirectoryObjectID(storeDirEncoded, + opts[LIST_OPTION_ALLOWOLD], + opts[LIST_OPTION_ALLOWDELETED]); + if(rootDir == 0) { - printf("Directory %s not found on store\n", args[0].c_str()); + printf("Directory '%s' not found on store\n", + args[0].c_str()); return; } } @@ -373,19 +392,16 @@ void BackupQueries::List(int64_t DirID, const std::string &rListRoot, const bool { // Display this entry BackupStoreFilenameClear clear(en->GetName()); - std::string line; // Object ID? if(!opts[LIST_OPTION_NOOBJECTID]) { // add object ID to line - char oid[32]; -#ifdef WIN32 - sprintf(oid, "%08I64x ", en->GetObjectID()); +#ifdef _MSC_VER + printf("%08I64x ", (int64_t)en->GetObjectID()); #else - sprintf(oid, "%08llx ", en->GetObjectID()); + printf("%08llx ", (long long)en->GetObjectID()); #endif - line += oid; } // Flags? @@ -412,57 +428,71 @@ void BackupQueries::List(int64_t DirID, const std::string &rListRoot, const bool // terminate *(f++) = ' '; *(f++) = '\0'; - line += displayflags; + printf(displayflags); + if(en_flags != 0) { - line += "[ERROR: Entry has additional flags set] "; + printf("[ERROR: Entry has additional flags set] "); } } if(opts[LIST_OPTION_TIMES]) { // Show times... - line += BoxTimeToISO8601String(en->GetModificationTime()); - line += ' '; + std::string time = BoxTimeToISO8601String( + en->GetModificationTime()); + printf("%s ", time.c_str()); } if(opts[LIST_OPTION_DISPLAY_HASH]) { - char hash[64]; -#ifdef WIN32 - ::sprintf(hash, "%016I64x ", en->GetAttributesHash()); +#ifdef _MSC_VER + printf("%016I64x ", (int64_t)en->GetAttributesHash()); #else - ::sprintf(hash, "%016llx ", en->GetAttributesHash()); + printf("%016llx ", (long long)en->GetAttributesHash()); #endif - line += hash; } if(opts[LIST_OPTION_SIZEINBLOCKS]) { - char num[32]; -#ifdef WIN32 - sprintf(num, "%05I64d ", en->GetSizeInBlocks()); +#ifdef _MSC_VER + printf("%05I64d ", (int64_t)en->GetSizeInBlocks()); #else - sprintf(num, "%05lld ", en->GetSizeInBlocks()); + printf("%05lld ", (long long)en->GetSizeInBlocks()); #endif - line += num; } // add name if(!FirstLevel) { - line += rListRoot; - line += '/'; +#ifdef WIN32 + std::string listRootDecoded; + if(!ConvertUtf8ToConsole(rListRoot.c_str(), + listRootDecoded)) return; + printf("%s/", listRootDecoded.c_str()); +#else + printf("%s/", rListRoot.c_str()); +#endif } - line += clear.GetClearFilename().c_str(); - if(!en->GetName().IsEncrypted()) +#ifdef WIN32 { - line += "[FILENAME NOT ENCRYPTED]"; + std::string fileName; + if(!ConvertUtf8ToConsole( + clear.GetClearFilename().c_str(), fileName)) + return; + printf("%s", fileName.c_str()); } +#else + printf("%s", clear.GetClearFilename().c_str()); +#endif - // print line - printf("%s\n", line.c_str()); + if(!en->GetName().IsEncrypted()) + { + printf("[FILENAME NOT ENCRYPTED]"); + } + + printf("\n"); // Directory? if((en->GetFlags() & BackupStoreDirectory::Entry::Flags_Dir) != 0) @@ -495,7 +525,7 @@ int64_t BackupQueries::FindDirectoryObjectID(const std::string &rDirName, bool A { // Split up string into elements std::vector<std::string> dirElements; - SplitString(rDirName, DIRECTORY_SEPARATOR_ASCHAR, dirElements); + SplitString(rDirName, '/', dirElements); // Start from current stack, or root, whichever is required std::vector<std::pair<std::string, int64_t> > stack; @@ -629,7 +659,14 @@ std::string BackupQueries::GetCurrentDirectoryName() for(unsigned int l = 0; l < mDirStack.size(); ++l) { r += "/"; +#ifdef WIN32 + std::string dirName; + if(!ConvertUtf8ToConsole(mDirStack[l].first.c_str(), dirName)) + return "error"; + r += dirName; +#else r += mDirStack[l].first; +#endif } return r; @@ -651,9 +688,17 @@ void BackupQueries::CommandChangeDir(const std::vector<std::string> &args, const printf("Incorrect usage.\ncd [-o] [-d] <directory>\n"); return; } + +#ifdef WIN32 + std::string dirName; + if(!ConvertConsoleToUtf8(args[0].c_str(), dirName)) return; +#else + const std::string& dirName(args[0]); +#endif std::vector<std::pair<std::string, int64_t> > newStack; - int64_t id = FindDirectoryObjectID(args[0], opts['o'], opts['d'], &newStack); + int64_t id = FindDirectoryObjectID(dirName, opts['o'], opts['d'], + &newStack); if(id == 0) { @@ -683,7 +728,14 @@ void BackupQueries::CommandChangeLocalDir(const std::vector<std::string> &args) } // Try changing directory - if(::chdir(args[0].c_str()) != 0) +#ifdef WIN32 + std::string dirName; + if(!ConvertConsoleToUtf8(args[0].c_str(), dirName)) return; + int result = ::chdir(dirName.c_str()); +#else + int result = ::chdir(args[0].c_str()); +#endif + if(result != 0) { printf((errno == ENOENT || errno == ENOTDIR)?"Directory '%s' does not exist\n":"Error changing dir to '%s'\n", args[0].c_str()); @@ -697,8 +749,13 @@ void BackupQueries::CommandChangeLocalDir(const std::vector<std::string> &args) printf("Error getting current directory\n"); return; } - + +#ifdef WIN32 + if(!ConvertUtf8ToConsole(wd, dirName)) return; + printf("Local current directory is now '%s'\n", dirName.c_str()); +#else printf("Local current directory is now '%s'\n", wd); +#endif } @@ -826,7 +883,14 @@ void BackupQueries::CommandGet(const std::vector<std::string> &args, const bool { // Specified by name, find the object in the directory to get the ID BackupStoreDirectory::Iterator i(dir); +#ifdef WIN32 + std::string fileName; + if(!ConvertConsoleToUtf8(args[0].c_str(), fileName)) + return; + BackupStoreFilenameClear fn(fileName); +#else BackupStoreFilenameClear fn(args[0]); +#endif BackupStoreDirectory::Entry *en = i.FindMatchingClearName(fn); if(en == 0) @@ -868,7 +932,7 @@ void BackupQueries::CommandGet(const std::vector<std::string> &args, const bool } catch(...) { - ::unlink(args[1].c_str()); + ::unlink(localName.c_str()); printf("Error occured fetching file.\n"); } } @@ -962,7 +1026,7 @@ void BackupQueries::CommandCompare(const std::vector<std::string> &args, const b } else { - printf("Warning: couldn't determine the time of the last syncronisation -- checks not performed.\n"); + printf("Warning: couldn't determine the time of the last synchronisation -- checks not performed.\n"); } } @@ -1049,7 +1113,7 @@ void BackupQueries::CompareLocation(const std::string &rLocation, BackupQueries: } // Then get it compared - Compare(std::string(DIRECTORY_SEPARATOR) + rLocation, + Compare(std::string("/") + rLocation, loc.GetKeyValue("Path"), rParams); } catch(...) @@ -1074,32 +1138,62 @@ void BackupQueries::CompareLocation(const std::string &rLocation, BackupQueries: // -------------------------------------------------------------------------- void BackupQueries::Compare(const std::string &rStoreDir, const std::string &rLocalDir, BackupQueries::CompareParams &rParams) { +#ifdef WIN32 + std::string storeDirEncoded; + if(!ConvertConsoleToUtf8(rStoreDir.c_str(), storeDirEncoded)) return; +#else + const std::string& storeDirEncoded(rStoreDir); +#endif + // Get the directory ID of the directory -- only use current data - int64_t dirID = FindDirectoryObjectID(rStoreDir); + int64_t dirID = FindDirectoryObjectID(storeDirEncoded); // Found? if(dirID == 0) { - printf("Local directory '%s' exists, but server directory '%s' does not exist\n", rLocalDir.c_str(), rStoreDir.c_str()); + printf("Local directory '%s' exists, but " + "server directory '%s' does not exist\n", + rLocalDir.c_str(), rStoreDir.c_str()); rParams.mDifferences ++; return; } + +#ifdef WIN32 + std::string localDirEncoded; + if(!ConvertConsoleToUtf8(rLocalDir.c_str(), localDirEncoded)) return; +#else + std::string localDirEncoded(rLocalDir); +#endif // Go! - Compare(dirID, rStoreDir, rLocalDir, rParams); + Compare(dirID, storeDirEncoded, localDirEncoded, rParams); } // -------------------------------------------------------------------------- // // Function -// Name: BackupQueries::Compare(int64_t, const std::string &, BackupQueries::CompareParams &) +// Name: BackupQueries::Compare(int64_t, const std::string &, +// const std::string &, BackupQueries::CompareParams &) // Purpose: Compare a store directory against a local directory // Created: 2003/10/13 // // -------------------------------------------------------------------------- void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const std::string &rLocalDir, BackupQueries::CompareParams &rParams) { +#ifdef WIN32 + // By this point, rStoreDir and rLocalDir should be in UTF-8 encoding + + std::string localName; + std::string storeName; + + if(!ConvertUtf8ToConsole(rLocalDir.c_str(), localName)) return; + if(!ConvertUtf8ToConsole(rStoreDir.c_str(), storeName)) return; +#else + const std::string& localName(rLocalDir); + const std::string& storeName(rStoreDir); +#endif + // Get info on the local directory struct stat st; if(::lstat(rLocalDir.c_str(), &st) != 0) @@ -1107,16 +1201,21 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s // What kind of error? if(errno == ENOTDIR) { - printf("Local object '%s' is a file, server object '%s' is a directory\n", rLocalDir.c_str(), rStoreDir.c_str()); + printf("Local object '%s' is a file, " + "server object '%s' is a directory\n", + localName.c_str(), storeName.c_str()); rParams.mDifferences ++; } else if(errno == ENOENT) { - printf("Local directory '%s' does not exist (compared to server directory '%s')\n", rLocalDir.c_str(), rStoreDir.c_str()); + printf("Local directory '%s' does not exist " + "(compared to server directory '%s')\n", + localName.c_str(), storeName.c_str()); } else { - printf("ERROR: stat on local dir '%s'\n", rLocalDir.c_str()); + printf("ERROR: stat on local dir '%s'\n", + localName.c_str()); } return; } @@ -1136,7 +1235,8 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s // Test out the attributes if(!dir.HasAttributes()) { - printf("Store directory '%s' doesn't have attributes.\n", rStoreDir.c_str()); + printf("Store directory '%s' doesn't have attributes.\n", + storeName.c_str()); } else { @@ -1146,12 +1246,14 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s // Get attributes of local directory BackupClientFileAttributes localAttr; - localAttr.ReadAttributes(rLocalDir.c_str(), true /* directories have zero mod times */); + localAttr.ReadAttributes(rLocalDir.c_str(), + true /* directories have zero mod times */); if(!(attr.Compare(localAttr, true, true /* ignore modification times */))) { - printf("Local directory '%s' has different attributes to store directory '%s'.\n", - rLocalDir.c_str(), rStoreDir.c_str()); + printf("Local directory '%s' has different attributes " + "to store directory '%s'.\n", + localName.c_str(), storeName.c_str()); rParams.mDifferences ++; } } @@ -1160,7 +1262,7 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s DIR *dirhandle = ::opendir(rLocalDir.c_str()); if(dirhandle == 0) { - printf("ERROR: opendir on local dir '%s'\n", rLocalDir.c_str()); + printf("ERROR: opendir on local dir '%s'\n", localName.c_str()); return; } try @@ -1217,7 +1319,8 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s // Close directory if(::closedir(dirhandle) != 0) { - printf("ERROR: closedir on local dir '%s'\n", rLocalDir.c_str()); + printf("ERROR: closedir on local dir '%s'\n", + localName.c_str()); } dirhandle = 0; @@ -1244,17 +1347,26 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s storeDirs.insert(std::pair<std::string, BackupStoreDirectory::Entry *>(name.GetClearFilename(), storeDirEn)); } } + +#ifdef _MSC_VER + typedef std::set<std::string>::iterator string_set_iter_t; +#else + typedef std::set<std::string>::const_iterator string_set_iter_t; +#endif // Now compare files. for(std::set<std::pair<std::string, BackupStoreDirectory::Entry *> >::const_iterator i = storeFiles.begin(); i != storeFiles.end(); ++i) { // Does the file exist locally? - std::set<std::string>::const_iterator local(localFiles.find(i->first)); + string_set_iter_t local(localFiles.find(i->first)); if(local == localFiles.end()) { // Not found -- report - printf("Local file '%s/%s' does not exist, but store file '%s/%s' does.\n", - rLocalDir.c_str(), i->first.c_str(), rStoreDir.c_str(), i->first.c_str()); + printf("Local file '%s" DIRECTORY_SEPARATOR + "%s' does not exist, " + "but store file '%s/%s' does.\n", + localName.c_str(), i->first.c_str(), + storeName.c_str(), i->first.c_str()); rParams.mDifferences ++; } else @@ -1320,8 +1432,11 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s true /* ignore attr mod time */, fileOnServerStream->IsSymLink() /* ignore modification time if it's a symlink */)) { - printf("Local file '%s/%s' has different attributes to store file '%s/%s'.\n", - rLocalDir.c_str(), i->first.c_str(), rStoreDir.c_str(), i->first.c_str()); + printf("Local file '%s" + DIRECTORY_SEPARATOR + "%s' has different attributes " + "to store file '%s/%s'.\n", + localName.c_str(), i->first.c_str(), storeName.c_str(), i->first.c_str()); rParams.mDifferences ++; if(modifiedAfterLastSync) { @@ -1385,8 +1500,11 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s // Report if not equal. if(!equal) { - printf("Local file '%s/%s' has different contents to store file '%s/%s'.\n", - rLocalDir.c_str(), i->first.c_str(), rStoreDir.c_str(), i->first.c_str()); + printf("Local file '%s" + DIRECTORY_SEPARATOR + "%s' has different contents " + "to store file '%s/%s'.\n", + localName.c_str(), i->first.c_str(), storeName.c_str(), i->first.c_str()); rParams.mDifferences ++; if(modifiedAfterLastSync) { @@ -1404,11 +1522,12 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s printf("ERROR: (%d/%d) during file fetch and comparsion for '%s/%s'\n", e.GetType(), e.GetSubType(), - rStoreDir.c_str(), i->first.c_str()); + storeName.c_str(), + i->first.c_str()); } catch(...) { - printf("ERROR: (unknown) during file fetch and comparsion for '%s/%s'\n", rStoreDir.c_str(), i->first.c_str()); + printf("ERROR: (unknown) during file fetch and comparsion for '%s/%s'\n", storeName.c_str(), i->first.c_str()); } // Remove from set so that we know it's been compared @@ -1417,20 +1536,25 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s } // Report any files which exist on the locally, but not on the store - for(std::set<std::string>::const_iterator i = localFiles.begin(); i != localFiles.end(); ++i) + for(string_set_iter_t i = localFiles.begin(); i != localFiles.end(); ++i) { - std::string localName(rLocalDir + DIRECTORY_SEPARATOR + *i); + std::string localFileName(rLocalDir + + DIRECTORY_SEPARATOR + *i); // Should this be ignored (ie is excluded)? - if(rParams.mpExcludeFiles == 0 || !(rParams.mpExcludeFiles->IsExcluded(localName))) + if(rParams.mpExcludeFiles == 0 || + !(rParams.mpExcludeFiles->IsExcluded(localFileName))) { - printf("Local file '%s/%s' exists, but store file '%s/%s' does not exist.\n", - rLocalDir.c_str(), (*i).c_str(), rStoreDir.c_str(), (*i).c_str()); + printf("Local file '%s" DIRECTORY_SEPARATOR + "%s' exists, but store file '%s/%s' " + "does not exist.\n", + localName.c_str(), (*i).c_str(), + storeName.c_str(), (*i).c_str()); rParams.mDifferences ++; // Check the file modification time { struct stat st; - if(::stat(localName.c_str(), &st) == 0) + if(::stat(localFileName.c_str(), &st) == 0) { if(FileModificationTime(st) > rParams.mLatestFileUploadTime) { @@ -1454,12 +1578,16 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s for(std::set<std::pair<std::string, BackupStoreDirectory::Entry *> >::const_iterator i = storeDirs.begin(); i != storeDirs.end(); ++i) { // Does the directory exist locally? - std::set<std::string>::const_iterator local(localDirs.find(i->first)); + string_set_iter_t local(localDirs.find(i->first)); if(local == localDirs.end()) { // Not found -- report - printf("Local directory '%s/%s' does not exist, but store directory '%s/%s' does.\n", - rLocalDir.c_str(), i->first.c_str(), rStoreDir.c_str(), i->first.c_str()); + printf("Local directory '%s" + DIRECTORY_SEPARATOR "%s' " + "does not exist, but store directory " + "'%s/%s' does.\n", + localName.c_str(), i->first.c_str(), + storeName.c_str(), i->first.c_str()); rParams.mDifferences ++; } else @@ -1479,8 +1607,10 @@ void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, const s // Should this be ignored (ie is excluded)? if(rParams.mpExcludeDirs == 0 || !(rParams.mpExcludeDirs->IsExcluded(localName))) { - printf("Local directory '%s/%s' exists, but store directory '%s/%s' does not exist.\n", - rLocalDir.c_str(), (*i).c_str(), rStoreDir.c_str(), (*i).c_str()); + printf("Local directory '%s/%s' exists, but " + "store directory '%s/%s' does not exist.\n", + localName.c_str(), (*i).c_str(), + storeName.c_str(), (*i).c_str()); rParams.mDifferences ++; } else @@ -1534,14 +1664,24 @@ void BackupQueries::CommandRestore(const std::vector<std::string> &args, const b } else { +#ifdef WIN32 + std::string storeDirEncoded; + if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) + return; +#else + const std::string& storeDirEncoded(args[0]); +#endif + // Look up directory ID - dirID = FindDirectoryObjectID(args[0], false /* no old versions */, restoreDeleted /* find deleted dirs */); + dirID = FindDirectoryObjectID(storeDirEncoded, + false /* no old versions */, + restoreDeleted /* find deleted dirs */); } // Allowable? if(dirID == 0) { - printf("Directory %s not found on server\n", args[0].c_str()); + printf("Directory '%s' not found on server\n", args[0].c_str()); return; } if(dirID == BackupProtocolClientListDirectory::RootDirectory) @@ -1550,9 +1690,18 @@ void BackupQueries::CommandRestore(const std::vector<std::string> &args, const b return; } +#ifdef WIN32 + std::string localName; + if(!ConvertConsoleToUtf8(args[1].c_str(), localName)) return; +#else + std::string localName(args[1]); +#endif + // Go and restore... - switch(BackupClientRestore(mrConnection, dirID, args[1].c_str(), true /* print progress dots */, restoreDeleted, - false /* don't undelete after restore! */, opts['r'] /* resume? */)) + switch(BackupClientRestore(mrConnection, dirID, localName.c_str(), + true /* print progress dots */, restoreDeleted, + false /* don't undelete after restore! */, + opts['r'] /* resume? */)) { case Restore_Complete: printf("Restore complete\n"); @@ -1691,26 +1840,29 @@ void BackupQueries::CommandUndelete(const std::vector<std::string> &args, const return; } +#ifdef WIN32 + std::string storeDirEncoded; + if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) return; +#else + const std::string& storeDirEncoded(args[0]); +#endif + // Get directory ID - int64_t dirID = FindDirectoryObjectID(args[0], false /* no old versions */, true /* find deleted dirs */); + int64_t dirID = FindDirectoryObjectID(storeDirEncoded, + false /* no old versions */, true /* find deleted dirs */); // Allowable? if(dirID == 0) { - printf("Directory %s not found on server\n", args[0].c_str()); + printf("Directory '%s' not found on server\n", args[0].c_str()); return; } if(dirID == BackupProtocolClientListDirectory::RootDirectory) { - printf("Cannot restore the root directory -- restore locations individually.\n"); + printf("Cannot undelete the root directory.\n"); return; } // Undelete mrConnection.QueryUndeleteDirectory(dirID); } - - - - - diff --git a/bin/bbackupquery/bbackupquery.cpp b/bin/bbackupquery/bbackupquery.cpp index 629f0eeb..abd0177b 100644 --- a/bin/bbackupquery/bbackupquery.cpp +++ b/bin/bbackupquery/bbackupquery.cpp @@ -9,7 +9,9 @@ #include "Box.h" -#include <unistd.h> +#ifdef HAVE_UNISTD_H + #include <unistd.h> +#endif #include <stdio.h> #include <sys/types.h> #ifdef HAVE_LIBREADLINE @@ -48,8 +50,13 @@ void PrintUsageAndExit() { - printf("Usage: bbackupquery [-q] [-c config_file] [-l log_file] [commands]\nAs many commands as you require.\n" \ - "If commands are multiple words, remember to enclose the command in quotes.\n" \ + printf("Usage: bbackupquery [-q] [-w] " +#ifdef WIN32 + "[-u] " +#endif + "\n\t[-c config_file] [-l log_file] [commands]\n" + "As many commands as you require.\n" + "If commands are multiple words, remember to enclose the command in quotes.\n" "Remember to use quit command if you don't want to drop into interactive mode.\n"); exit(1); } @@ -64,7 +71,7 @@ int main(int argc, const char *argv[]) // Under Win32 we must initialise the Winsock library // before using it. - if (WSAStartup(MAKELONG(1, 1), &info) == SOCKET_ERROR) + if (WSAStartup(0x0101, &info) == SOCKET_ERROR) { // throw error? perhaps give it its own id in the furture THROW_EXCEPTION(BackupStoreException, Internal) @@ -88,10 +95,17 @@ int main(int argc, const char *argv[]) // Flags bool quiet = false; bool readWrite = false; - + +#ifdef WIN32 + const char* validOpts = "qwuc:l:"; + bool unicodeConsole = false; +#else + const char* validOpts = "qwc:l:"; +#endif + // See if there's another entry on the command line int c; - while((c = getopt(argc, (char * const *)argv, "qwc:l:")) != -1) + while((c = getopt(argc, (char * const *)argv, validOpts)) != -1) { switch(c) { @@ -118,6 +132,12 @@ int main(int argc, const char *argv[]) printf("Can't open log file '%s'\n", optarg); } break; + +#ifdef WIN32 + case 'u': + unicodeConsole = true; + break; +#endif case '?': default: @@ -135,6 +155,30 @@ int main(int argc, const char *argv[]) printf(banner); } +#ifdef WIN32 + if (unicodeConsole) + { + if (!SetConsoleCP(CP_UTF8)) + { + fprintf(stderr, "Failed to set input codepage: " + "error %d\n", GetLastError()); + } + + if (!SetConsoleOutputCP(CP_UTF8)) + { + fprintf(stderr, "Failed to set output codepage: " + "error %d\n", GetLastError()); + } + + // enable input of Unicode characters + if (_setmode(_fileno(stdin), _O_TEXT) == -1) + { + perror("Failed to set the console input to " + "binary mode"); + } + } +#endif // WIN32 + // Read in the configuration file if(!quiet) printf("Using configuration file %s\n", configFilename); std::string errs; |